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;
}
 
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
 
Zurück