0

他のすべてのプロセスからすべてのコンポーネントを受け取った後、マスタープロセスから動的に割り当てられた2次元配列を出力しようとしています。コンポーネントとは、サブアレイまたはブロックを意味します。MPI C - 2番目の配列セグメントを1つのグローバル配列に集める

私はコードをプロセスの数に汎用化しました。次の図は、ブロックが完全な配列にどのように配置されているかを見るのに役立ちます。各ブロックは1つのプロセスで処理されます。

:これは、特に12のプロセスのシナリオを対象図は、ある

mpiexec -n 12 ./gather2dArray 

:ちょうどしかしここでは、コマンドを使用して、のは、私は12個のプロセスを(ネイティブ私は8つのコアを持っている)を使用してプログラムを実行することを想定してみましょう

enter image description here

このquestionのジョナサンの答えは私を大いに助けましたが、残念ながら私が望むものを完全に実装することはできませんでした。

まず、各プロセスにブロックを作成します。これらのブロックの名前はgridです。すべての配列は、動的に割り当てられた2次元配列です。また、グローバル配列(universe)をmasterプロセス(#0)でしか表示されないように作成します。

最後に、すべてのサブアレイをグローバル配列にアセンブルするためにMPI_Gatherv(...)を使用する必要があります。次に、ローカル配列とグローバル配列を表示します。

上記のコマンドでプログラムを実行すると、MPI_Gatherv(...)機能に到達するとセグメンテーションフォルトが発生します。私は何が間違っているのか分かりません。私はコード内のいくつかの過ちを修正した

編集:私は、以下の(多くのコメント)完全なコードを提供してきました。今度はMPI_Gatherv()がやや成功しています。グローバル配列の最初の行全体を正しく印刷できます(プロセスの個々の要素をチェックし、常に一致します)。しかし、私が第2列に到達すると、いくつかの象形文字が現れ、最終的にセグメンテーション違反が現れます。私はそこに何が間違っているのか理解できませんでした。まだそれを見て..

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

void print2dCharArray(char** array, int rows, int columns); 


int main(int argc, char** argv) 
{ 
    int master = 0, np, rank; 
    char version[10]; 
    char processorName[20]; 
    int strLen[10]; 

    // Initialize MPI environment 
    MPI_Init(&argc, &argv); 

    MPI_Comm_size(MPI_COMM_WORLD, &np); 
    if (np != 12) { MPI_Abort(MPI_COMM_WORLD,1); } 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

    // We need a different seed for each process 
    srand(time(0)^(rank * 33/4)); 

    int nDims = 2;    // array dimensions 
    int rows = 4, columns = 6; // rows and columns of each block 
    int prows = 3, pcolumns = 4; // rows and columns of blocks. Each block is handled by 1 process 

    char** grid = malloc(rows * sizeof(char*)); 
    for (int i = 0; i < rows; i++) 
    grid[i] = malloc(columns * sizeof(char)); 

    char** universe = NULL;   // Global array 
    char* recvPtr;     // Pointer to start of Global array 
    int Rows = rows * prows;   // Global array rows 
    int Columns = columns * pcolumns; // Global array columns 
    int sizes[2];      // No of elements in each dimension of the whole array 
    int subSizes[2];     // No of elements in each dimension of the subarray 
    int startCoords[2];    // Starting coordinates of each subarray 
    MPI_Datatype recvBlock, recvMagicBlock; 

    if (rank == master){   // For the master's eyes only 
    universe = malloc(Rows * sizeof(char*)); 
    for (int i = 0; i < Rows; i++) 
     universe[i] = malloc(Columns * sizeof(char)); 

    // Create a subarray (a rectangular block) datatype from a regular, 2d array 
    sizes[0] = Rows; 
    sizes[1] = Columns; 
    subSizes[0] = rows; 
    subSizes[1] = columns; 
    startCoords[0] = 0; 
    startCoords[1] = 0; 

    MPI_Type_create_subarray(nDims, sizes, subSizes, startCoords, MPI_ORDER_C, MPI_CHAR, &recvBlock); 

    // Now modify the newly created datatype to fit our needs, by specifying 
    // (lower bound remains the same = 0) 
    // - new extent 
    // The new region/block will now "change" sooner, as soon as we reach a region of elements 
    //   occupied by a new block, ie. every: (columns) * sizeof(elementType) = 
    MPI_Type_create_resized(recvBlock, 0, columns * sizeof(char), &recvMagicBlock); 

    MPI_Type_commit(&recvMagicBlock); 
    recvPtr = &universe[0][0]; 
    } 

    // populate arrays 
    for (int y = 0; y < rows; y++){ 
    for (int x = 0; x < columns; x++){ 
     if (((double) rand()/RAND_MAX) <= density) 
    grid[y][x] = '#'; 
     else 
     grid[y][x] = '.'; 
    } 
    } 


    // display local array 
    for (int i = 0; i < np; i++){ 
    if (i == rank) { 
     printf("\n[Rank] of [total]: No%d of %d\n", rank, np); 
     print2dCharArray(grid, rows, columns); 
    } 
    MPI_Barrier(MPI_COMM_WORLD); 
    } 


    /* MPI_Gathering.. */ 
    int recvCounts[np], displacements[np]; 

    // recvCounts: how many chunks of data each process has -- in units of blocks here -- 
    for (int i = 0; i < np; i++) 
    recvCounts[i] = 1; 

    // prows * pcolumns = np 
    // displacements: displacement relative to global buffer (universe) at which to place the 
    //        incoming data block from process i -- in block extents! -- 
    int index = 0; 
    for (int p_row = 0; p_row < prows; p_row++) 
    for (int p_column = 0; p_column < pcolumns; p_column++) 
     displacements[index++] = p_column + p_row * (rows * pcolumns); 

    // MPI_Gatherv(...) is a collective routine 
    // Gather the local arrays to the global array in the master process 
    // send type: MPI_CHAR  (a char) 
    // recv type: recvMagicBlock (a block) 
    MPI_Gatherv(&grid[0][0], rows * columns, MPI_CHAR, //: parameters relevant to sender 
      recvPtr, recvCounts, displacements, recvMagicBlock, master, //: parameters relevant to receiver 
      MPI_COMM_WORLD); 

    // display global array 
    MPI_Barrier(MPI_COMM_WORLD); 
    if (rank == master){ 
    printf("\n---Global Array---\n"); 
    print2dCharArray(universe, Rows, Columns); 
    } 

    MPI_Finalize(); 
    return 0; 
} 


void print2dCharArray(char** array, int rows, int columns) 
{ 
    int i, j; 
    for (i = 0; i < rows; i++){ 
    for (j = 0; j < columns; j++){ 
     printf("%c ", array[i][j]); 
    } 
    printf("\n"); 
    } 
    fflush(stdout); 
} 

次は私が得ている出力です。私が何をしようと、私はこれを越えることはできません。ご覧のように、グローバル配列の最初の行は、4つのプロセスの最初の4つのブロックを使用して正しく印刷されます。次の行にジャンプすると、象形文字が得られます。

[email protected]:~/mpi$ mpiexec -n 12 ./gather2darray 
MPICH Version: 3User 
Processor name: User 

[Rank] of [total]: No0 of 12 
. . # . . # 
# . # # # . 
. . . # # . 
. . # . . . 

[Rank] of [total]: No1 of 12 
. . # # . . 
. . . . # # 
. # . . # . 
. . # . . . 

[Rank] of [total]: No2 of 12 
. # # # . # 
. # . . . . 
# # # . . . 
. . . # # . 

[Rank] of [total]: No3 of 12 
. . # # # # 
. . # # . . 
# . # . # . 
. . . # . . 

[Rank] of [total]: No4 of 12 
. # . . . # 
# . # . # . 
# . . . . . 
# . . . . . 

[Rank] of [total]: No5 of 12 
# # . # # . 
# . . # # . 
. . . . # . 
. # # . . . 

[Rank] of [total]: No6 of 12 
. . # # . # 
. . # . # . 
# . . . . . 
. . . # # # 

[Rank] of [total]: No7 of 12 
# # . # # . 
. # # . . . 
. . . . . # 
. . . # # . 

[Rank] of [total]: No8 of 12 
. # . . . . 
# . # . # . 
. . . # . # 
# . # # # . 

[Rank] of [total]: No9 of 12 
. . . . . # 
. . # . . . 
. . # . . # 
. . # # . . 

[Rank] of [total]: No10 of 12 
. . . . # . 
# . . . . . 
. . # # . . 
. . . # . # 

[Rank] of [total]: No11 of 12 
. # . . # . 
. # . # # . 
. . . # . . 
. # . # . # 

---Global Array--- 
. . # . . # . . # # . . . # # # . # . . # # # # 
� � < * � � e { � � � � �  � 
    J      









*** Error in `./gather2darray': double free or corruption (out): 0x0000000001e4c050 *** 
*** stack smashing detected ***: ./gather2darray terminated 
*** stack smashing detected ***: ./gather2darray terminated 
*** stack smashing detected ***: ./gather2darray terminated 
*** stack smashing detected ***: ./gather2darray terminated 
*** stack smashing detected ***: ./gather2darray terminated 
*** stack smashing detected ***: ./gather2darray terminated 
*** stack smashing detected ***: ./gather2darray terminated 
*** stack smashing detected ***: ./gather2darray terminated 
*** stack smashing detected ***: ./gather2darray terminated 
*** stack smashing detected ***: ./gather2darray terminated 
*** stack smashing detected ***: ./gather2darray terminated 

=================================================================================== 
= BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES 
= PID 10979 RUNNING AT User 
= EXIT CODE: 139 
= CLEANING UP REMAINING PROCESSES 
= YOU CAN IGNORE THE BELOW CLEANUP MESSAGES 
=================================================================================== 
YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11) 
This typically refers to a problem with your application. 
Please see the FAQ page for debugging suggestions 

ヘルプは非常に高く評価されます。前もって感謝します。

答えて

1

あなたのコードはほぼ正しいですが、あなたはMPIの重要な原則を忘れてしまっただけです。 MPI関数で配列を使用している場合、MPIは配列メモリが連続的に割り当てられているとみなします。だから、あなたは2 dims配列の割り当てを変更する必要があります。

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

    void print2dCharArray(char** array, int rows, int columns); 


    int main(int argc, char** argv) 
    { 
    int master = 0, np, rank; 
    char version[10]; 
    char processorName[20]; 
    int strLen[10]; 

    // Initialize MPI environment 
    MPI_Init(&argc, &argv); 

    MPI_Comm_size(MPI_COMM_WORLD, &np); 
    if (np != 12) { MPI_Abort(MPI_COMM_WORLD,1); } 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

    // We need a different seed for each process 
    srand(time(0)^(rank * 33/4)); 

    int nDims = 2;    // array dimensions 
    int rows = 4, columns = 6; // rows and columns of each block 
    int prows = 3, pcolumns = 4; // rows and columns of blocks. Each block is handled by 1 process 

    char* pre_grid = (char*) malloc(rows * columns * sizeof(char)); 
    char** grid = (char**) malloc(rows * sizeof(char*)); 
    for (int i = 0; i < rows; i++) 
     grid[i] = &(pre_grid[i * columns]); 

    char** universe = NULL;   // Global array 
    char* pre_universe = NULL; 
    char* recvPtr;     // Pointer to start of Global array 
    int Rows = rows * prows;   // Global array rows 
    int Columns = columns * pcolumns; // Global array columns 
    int sizes[2];      // No of elements in each dimension of the whole array 
    int subSizes[2];     // No of elements in each dimension of the subarray 
    int startCoords[2];    // Starting coordinates of each subarray 
    MPI_Datatype recvBlock, recvMagicBlock; 

    if (rank == master){   // For the master's eyes only 
    /* universe = malloc(Rows * sizeof(char*));*/ 
    /* for (int i = 0; i < Rows; i++)*/ 
    /*  universe[i] = malloc(Columns * sizeof(char));*/ 

     pre_universe = (char*) malloc(Rows * Columns * sizeof(char)); 
     universe = (char**) malloc(Rows * sizeof(char*)); 
     for (int i = 0; i < Rows; i++) { 
      universe[i] = &(pre_universe[i * Columns]); 
     } 



     // Create a subarray (a rectangular block) datatype from a regular, 2d array 
     sizes[0] = Rows; 
     sizes[1] = Columns; 
     subSizes[0] = rows; 
     subSizes[1] = columns; 
     startCoords[0] = 0; 
     startCoords[1] = 0; 

     MPI_Type_create_subarray(nDims, sizes, subSizes, startCoords, MPI_ORDER_C, MPI_CHAR, &recvBlock); 

     // Now modify the newly created datatype to fit our needs, by specifying 
     // (lower bound remains the same = 0) 
     // - new extent 
     // The new region/block will now "change" sooner, as soon as we reach a region of elements 
     //   occupied by a new block, ie. every: (columns) * sizeof(elementType) = 
     MPI_Type_create_resized(recvBlock, 0, columns * sizeof(char), &recvMagicBlock); 

     MPI_Type_commit(&recvMagicBlock); 
     recvPtr = &universe[0][0]; 
    } 

    // populate arrays 
    for (int y = 0; y < rows; y++){ 
     for (int x = 0; x < columns; x++){ 
     grid[y][x] = rank + 65; 
     } 
    } 


    // display local array 
    for (int i = 0; i < np; i++){ 
     if (i == rank) { 
     printf("\n[Rank] of [total]: No%d of %d\n", rank, np); 
     print2dCharArray(grid, rows, columns); 
     } 
     MPI_Barrier(MPI_COMM_WORLD); 
    } 


    /* MPI_Gathering.. */ 
    int recvCounts[np], displacements[np]; 

    // recvCounts: how many chunks of data each process has -- in units of blocks here -- 
    for (int i = 0; i < np; i++) 
     recvCounts[i] = 1; 

    // prows * pcolumns = np 
    // displacements: displacement relative to global buffer (universe) at which to place the 
    //        incoming data block from process i -- in block extents! -- 
    int index = 0; 
    for (int p_row = 0; p_row < prows; p_row++) 
     for (int p_column = 0; p_column < pcolumns; p_column++) 
     displacements[index++] = p_column + p_row * (rows * pcolumns); 

    // MPI_Gatherv(...) is a collective routine 
    // Gather the local arrays to the global array in the master process 
    // send type: MPI_CHAR  (a char) 
    // recv type: recvMagicBlock (a block) 
    MPI_Gatherv(&grid[0][0], rows * columns, MPI_CHAR, //: parameters relevant to sender 
      recvPtr, recvCounts, displacements, recvMagicBlock, master, //: parameters relevant to receiver 
      MPI_COMM_WORLD); 

    // display global array 
    MPI_Barrier(MPI_COMM_WORLD); 
    if (rank == master){ 
     printf("\n---Global Array---\n"); 
     print2dCharArray(universe, Rows, Columns); 
    } 

    free(grid[0]); 
    free(grid); 
    if (rank == master) { 
     free(universe[0]); 
     free(universe); 
     MPI_Type_free(&recvMagicBlock); 
     MPI_Type_free(&recvBlock); 
    } 


    MPI_Finalize(); 
    return 0; 
    } 


    void print2dCharArray(char** array, int rows, int columns) 
    { 
    int i, j; 
    for (i = 0; i < rows; i++){ 
     for (j = 0; j < columns; j++){ 
     printf("%c ", array[i][j]); 
     } 
     printf("\n"); 
    } 
    fflush(stdout); 
    } 

出力:

---Global Array--- 
    A A A A A A B B B B B B C C C C C C D D D D D D 
    A A A A A A B B B B B B C C C C C C D D D D D D 
    A A A A A A B B B B B B C C C C C C D D D D D D 
    A A A A A A B B B B B B C C C C C C D D D D D D 
    E E E E E E F F F F F F G G G G G G H H H H H H 
    E E E E E E F F F F F F G G G G G G H H H H H H 
    E E E E E E F F F F F F G G G G G G H H H H H H 
    E E E E E E F F F F F F G G G G G G H H H H H H 
    I I I I I I J J J J J J K K K K K K L L L L L L 
    I I I I I I J J J J J J K K K K K K L L L L L L 
    I I I I I I J J J J J J K K K K K K L L L L L L 
    I I I I I I J J J J J J K K K K K K L L L L L L 
+0

これをチェックするためにありがとうございました!早くあなたの答えを確認することができませんでした。私は急いではなかったので、このプロジェクトを延期しました。しかし今、時間が来て、私はあなたの答えを見ました。あなたはそうだった。どのような間違い。再度、感謝します! –

関連する問題