Verständnisfrage: Erstellung einer 3D-Matrix in MPI


AlanHorman

Mitglied
Ich muss mit MPI eine folgende Aufgabe lösen, doch ich habe ein Verständnisproblem:

Schreiben Sie ein MPI-Programm in dem eine
3-dimensionale Matrix (xyz) auf Knoten 0 erstellt wird.

Die Matrix wird gleichmäßig auf alle Knoten verteilt.
Jeder Knoten bestimmt für jede xy-Koordinate den Maximalen z-Wert und speichert
diesen in einer 2-dimensionalen Matrix.

Die einzelnen Teillösungen sollen schließlich
auf Knoten 0 zusammengefügt werden.
Der erste Schritt lief erfolgreich. Beim zweiten Schritt bin ich mir unsicher, ob ich jetzt eine ganze Matrix oder nur eine Teilmatrix für jeden Knoten / Prozessor erstellen soll.
Wenn es am Ende wieder zusammengefügt wird, würde es doch Sinn machen, dass im Knoten 0 eine neue Matrix entsteht? Oder verstehe ich was falsch?

Ich habe soweit die Aufgabe wie folgt programmiert:

C:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <mpi.h>

#define FROM_MASTER 1
#define FROM_NODE   2
#define N 5

/*
 * Author: RW
 * Date: 14.09.2020
 *
 */
 
 /*

float*** setRandomNumbers2Matrix(float*** matrix, int _size)
{
    srand(time(0));
    for (int i = 0; i < _size; i++)
    {
        for (int j = 0; j < _size; j++)
        {
            for (int k = 0; k < _size; k++)
            {
                matrix[i][j][k] = (rand() % 100) / 10.0;
            }
        }
    }
    
    return matrix;
}

float*** init3DMatrix(int _size)
{
    float*** matrix = (float***) malloc(_size * sizeof(float**));

    for (int x = 0; x < _size; x++)
    {
        matrix[x] = (float**) malloc(_size * sizeof(float*));   
        
        for (int y = 0; y < _size; y++)
        {
            matrix[x][y] = (float*) malloc(_size * sizeof(float));   
        }
    }

    return setRandomNumbers2Matrix(matrix, _size);
}

float** init2DMatrix(int _size)
{
    float** matrix = (float**) malloc(_size * sizeof(float*));

    for (int x = 0; x < _size; x++)
    {
        matrix[x] = (float*) malloc(_size * sizeof(float));   
    }

    return matrix;
}
*/

float maxValue(float* array, int _size)
{
    float v = 0.0;
    
    for (int i = 0; i < _size; i++)
    {
        if (array[i] >= v)
        {
            v = array[i];
        }   
    }
    
    return v;
}

int main(int argc, char** argv)
{
    MPI_Init (&argc, &argv);
    
    int rank;
    int size;
    
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Status status;
    
    //float** matrix2D = init2DMatrix(N);   
    float matrix2D[N][N];
    float matrix3D[N][N][N];
    
    int dest;
    int source;
    
    int nodes = size-1;
    
    int averow;
    int avecol;
    int offset;
    int extra;
    int rows;
    
    float* globaldata = NULL;

    
    if (rank == 0)
    {
        averow = N / nodes;
        offset = 0;
        extra = N % nodes;
        
        srand(time(0));
        
        // Es wurde ein statisches 3D-Array deklariert,
        // weil die Pointer-Variante sehr fehlerbehaftet waren.
        // float*** init3DMatrix(int _size) wurde entfernt.
        
        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < N; j++)
            {
                for (int k = 0; k < N; k++)
                {
                    matrix3D[i][j][k] = (rand() % 100) / 10.0;
                }
            }
        }
        
        for (dest = 1; dest <= nodes; dest++)
        {
                rows = (dest <= extra) ? averow+1 : averow;
            MPI_Send(&offset, 1, MPI_INT, dest, FROM_MASTER, MPI_COMM_WORLD);
            MPI_Send(&rows, 1, MPI_INT, dest, FROM_MASTER, MPI_COMM_WORLD);
            MPI_Send(&matrix3D[offset][0][0], rows*N*N, MPI_FLOAT, dest, FROM_MASTER, MPI_COMM_WORLD);
            offset = offset + rows;           
        }
        

    }
    
    if (rank > 0)
    {
          MPI_Recv(&offset, 1, MPI_INT, 0, FROM_MASTER, MPI_COMM_WORLD, &status);
          MPI_Recv(&rows, 1, MPI_INT, 0, FROM_MASTER, MPI_COMM_WORLD, &status);
          MPI_Recv(&matrix3D, rows*N*N, MPI_FLOAT, 0, FROM_MASTER, MPI_COMM_WORLD, &status);
          
          for (int x = 0; x < rows; x++)
          {
            for (int y = 0; y < N; y++)
            {
                float _maxValue = maxValue(matrix3D[x][y], N);
                matrix2D[rows][N] = _maxValue;
            }
          }
    }


    MPI_Finalize();
    return 0;
}
 

Technipion

Erfahrenes Mitglied
Hi AlanHorman, ist das Problem noch aktuell?

Der erste Schritt lief erfolgreich. Beim zweiten Schritt bin ich mir unsicher, ob ich jetzt eine ganze Matrix oder nur eine Teilmatrix für jeden Knoten / Prozessor erstellen soll.
In der Tat, so geht es mir auch. Von welchen "Knoten" ist denn da eigentlich die Rede? Ich verstehe nicht, wie man eine 3×3 Matrix "gleichmäßig verteilen" soll?

Jeder Knoten bestimmt für jede xy-Koordinate den Maximalen z-Wert und speichert
diesen in einer 2-dimensionalen Matrix.
Und wie kann man einen z-Wert in einer 2×2 Matrix speichern?

Gibt es vielleicht noch irgendwelchen zusätzlichen Informationen auf deinem Aufgabenblatt?

Gruß Technipion