3

いくつかのプロセスによって並行して操作されている2D倍精度配列があります。各プロセスは配列の一部を操作し、すべての反復の終わりに、すべてのプロセスが2D配列の同じコピーを持っていることを確認する必要があります。

サイズ10*10および2プロセス(またはプロセッサー)の配列を想定しています。プロセス1(P1)は2D行の最初の5行(合計5 * 10 = 50要素)を操作し、P2は最後の5行(合計50要素)を操作します。そして、各反復の終わりに、P1が必要です(それ自体の最初の5行+ P2の最後の5行)。P2は(P1の最初の5行+それはOWNの最後の5行)を持つ必要があります。シナリオが明確であることを願っています。

以下のコードを使用してブロードキャストしようとしています。しかし、私のプログラムは次のエラーで終了し続けます:「アプリケーションは終了文字列で終了しました:ハングアップ(信号1)」。

ここで指摘されているように、私はすでに連続した2Dメモリアロケータを使用しています。MPI_BcastはJonathanによる動的な2D配列です。しかし、それでも同じエラーが発生します。

誰かが私を助けることができますか?

私のコード:

double **grid, **oldgrid;
int gridsize; // size of grid
int rank, size; // rank of current process and no. of processes
int rowsforeachprocess, offset; // to keep track of rows that need to be handled by each process

 /* allocation, MPI_Init, and lots of other stuff */

 rowsforeachprocess = ceil((float)gridsize/size);
 offset = rank*rowsforeachprocess;

 /* Each process is handling "rowsforeachprocess" #rows.
 * Lots of work done here
 * Now I need to broadcast these rows to all other processes.
 */

 for(i=0; i<gridsize; i++){
     MPI_Bcast(&(oldgrid[i]), gridsize-2, MPI_DOUBLE, (i/rowsforeachprocess), MPI_COMM_WORLD);
 }

パート2:上記のコードは、1D分解を使用したラプラス方程式の並列ソルバーの一部であり、マスターワーカーモデルを使用したくありませんでした。マスターワーカーモデルを使用すると、コードが簡単になりますか?

4

1 に答える 1

2

ここでのクラッシュの原因となる問題は、2次元配列ポインターの問題です-&(oldgrid [i])は、doubleへのポインターではなく、doubleへのポインターであり、の行iへのポインターを指します。配列の行iではなく、配列。あなたが欲しいMPI_Bcast(&(oldgrid[i][0]),..MPI_Bcast(oldgrid[i],...

これを行う別の方法もあります。これは、行ごとに1つではなく、1つの高価な集合コミュニケーターのみを使用します。全員にアレイ全体のコピーが必要な場合は、MPI_Allgatherを使用してデータを収集し、全員に配布できます。または、プロセスの行数が同じでない一般的なケースでは、MPI_Allgathervです。ブロードキャストのループの代わりに、これは少し次のようになります。

{
    int *counts = malloc(size*sizeof(int));
    int *displs = malloc(size*sizeof(int));
    for (int i=0; i<size; i++) {
        counts[i] = rowsforeachprocess*gridsize;
        displs[i] = i*rowsforeachprocess*gridsize;
    }
    counts[size-1] = (gridsize-(size-1)*rowsforeachprocess)*gridsize;

    MPI_Allgatherv(oldgrid[offset], mynumrows*gridsize, MPI_DOUBLE,
                   oldgrid[0],      counts, displs, MPI_DOUBLE, MPI_COMM_WORLD);
    free(counts);
    free(displs);
}

ここで、countsは各タスクによって送信されたアイテムの数であり、displsは変位です。

しかし最後に、すべてのプロセスに配列全体のコピーが必要であることを確認しますか?ラプラシアンを計算するだけの場合は、配列全体ではなく、隣接する行が必要になる可能性があります。

これは次のようになります。

int main(int argc, char**argv) {
double **oldgrid;
const int gridsize=10; // size of grid
int rank, size;        // rank of current process and no. of processes
int rowsforeachprocess; // to keep track of rows that need to be handled by each process
int offset, mynumrows;
MPI_Status status;

MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

rowsforeachprocess = (int)ceil((float)gridsize/size);
offset = rank*rowsforeachprocess;
mynumrows = rowsforeachprocess;
if (rank == size-1)
    mynumrows = gridsize-offset;

rowsforeachprocess = (int)ceil((float)gridsize/size);
offset = rank*rowsforeachprocess;
mynumrows = rowsforeachprocess;
if (rank == size-1)
    mynumrows = gridsize-offset;

malloc2ddouble(&oldgrid, mynumrows+2, gridsize);

for (int i=0; i<mynumrows+2; i++)
    for (int j=0; j<gridsize; j++)
        oldgrid[i][j] = rank;

/* exchange row data with neighbours */
int highneigh = rank+1;
if (rank == size-1) highneigh = 0;

int lowneigh  = rank-1;
if (rank == 0)  lowneigh = size-1;

/* send data to high neibhour and receive from low */

MPI_Sendrecv(oldgrid[mynumrows], gridsize, MPI_DOUBLE, highneigh, 1,
             oldgrid[0],         gridsize, MPI_DOUBLE, lowneigh,  1,
             MPI_COMM_WORLD, &status);

/* send data to low neibhour and receive from high */

MPI_Sendrecv(oldgrid[1],           gridsize, MPI_DOUBLE, lowneigh,  1,
             oldgrid[mynumrows+1], gridsize, MPI_DOUBLE, highneigh, 1,
             MPI_COMM_WORLD, &status);


for (int proc=0; proc<size; proc++) {
    if (rank == proc) {
        printf("Rank %d:\n", proc);
        for (int i=0; i<mynumrows+2; i++) {
            for (int j=0; j<gridsize; j++) {
                printf("%f ", oldgrid[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }
    MPI_Barrier(MPI_COMM_WORLD);
}
于 2011-12-01T22:36:20.827 に答える