2017-06-22 5 views
0

npプロセスとnp異なる長さの配列がそれぞれ1つずつあります。私はそれらのうちの1つをすべてに送る必要があります(すべてのプロセスで同じことを繰り返します)。 np部品の1つがそのプロセスに留まるべきです。 3つのプロセスの場合各プロセスに異なる長さのアレイを集める

にすべきである:

p0[A1 B1 C1]を有し、最終的に[B0 B1 B2]

p2[A2 B2 C2]を有し、最終的に持つべきである持つべき[A0 B0 C0]を有し、最終的に[A0 A1 A2]

p1を有するべきです[C0 C1 C2]

より良い方法や

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

int main(int argc, char **argv) { 

    MPI_Init(&argc, &argv); 

    int rank, size; 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &size); 
    if(size!=3){ 
    MPI_Finalize(); 
    printf("execution with np = 3 only\n"); 
    return 1; 
    } 

    int a[5],b[5],c[5],len_a,len_b,len_c; 

    if(rank == 0){ 
    a[0] = 0 ; 
    b[0] = 30; 
    c[0] = 60; 
    len_a = len_b = len_c = 1; 
    //a,b,c can have different lengths 
    } 
    else if(rank == 1){ 
    a[0] = 1 ; a[1] = 11; 
    b[0] = 31; b[1] = 41; 
    c[0] = 61; c[1] = 71; 
    len_a = len_b = len_c = 2; 
    //a,b,c can have different lengths 
    } 
    else if(rank == 2){ 
    a[0] = 2 ; a[1] = 12; a[2] = 22; 
    b[0] = 32; b[1] = 42; b[2] = 52; 
    c[0] = 62; c[1] = 72; c[2] = 82; 
    len_a = len_b = len_c = 3; 
    //a,b,c can have different lengths 
    } 

    /* 

    At the end I should have 

    rank 0 : a = { 0 | 1 11 | 2 12 22 } 
    rank 1 : b = { 30 | 31 41 | 32 42 52 } 
    rank 2 : c = { 60 | 61 71 | 62 72 82 } 

    */ 

    int lengths[3]; 
    int tot_length; 

    /* 
    * we Gather the lengths for every process as root 
    */ 

    int mylen,i,root = 0; 

    for(i=0;i<3;i++){ 
    root = i; 

    mylen = rank + 1; 

    MPI_Gather(&mylen, 
      1, 
      MPI_INT, 
       lengths, 
      1, 
       MPI_INT, 
       root, 
       MPI_COMM_WORLD); 

    } 

    /* 
    calculate tot_length of my elem array 
    and determine the disp vector 
    */ 

    int displs[3]; 
    displs[0] = 0; 
    tot_length = lengths[0]; 

    for(i=1;i<3;i++){ 
    displs[i] = displs[i-1] + lengths[i-1]; 
    tot_length += lengths[i]; 
    } 

    printf("rank %d lengths = %d %d %d displs = %d %d %d \n", rank, \ 
     lengths[0],lengths[1],lengths[2],       \ 
     displs[0],displs[1],displs[2]); 

    int *elem = malloc(tot_length * sizeof(int)); 
    int myvec[5]; 
    int j; 

    for(i=0;i<3;i++){ 

    root = i; 
    if(root == 0){ 
     for(j=0;j<5;j++) 
     myvec[j]=a[j]; 
    } 
    else if(root == 1){ 
     for(j=0;j<5;j++) 
     myvec[j]=b[j]; 
    } 
    else if(root == 2){ 
     for(j=0;j<5;j++) 
     myvec[j]=c[j]; 
    } 

    MPI_Gatherv(myvec, 
       mylen, 
       MPI_INT, 
       elem, 
       lengths, 
       displs, 
       MPI_INT, 
       root, 
       MPI_COMM_WORLD); 

    } 

    printf("rank %d elem : ",rank); 
    for(i=0;i<tot_length;i++){ 
    printf("%d ", elem[i]); 
    } 
    printf("\n"); 


    MPI_Finalize(); 
    return 0; 
} 

あり:

私の考えは、メモリを割り当て、最後になどの共有情報と同時にルートのランクを変更MPI_gatherv操作を行うには、まずすべての長さを集めることでしたこの操作を行うための効率的な組み込み関数ですか?

答えて

2

最初にMPI_Gatherループの代わりにMPI_Allgatherを使用して長さを分散することができます。

次に、あなたが記述操作がMPI_Alltoall操作です:

illustration of All_gather/Alltoall

しかし、異なる変数にデータを持つことが、物事を複雑にします。 MPI_Bottom/type voodooを使用することもできますが、異なるランクのデータを連続した配列に配置してから、MPI_Alltoallvを使用して配布することをお勧めします。

+0

ありがとうございます。これは私が探していたものです!もちろん、私が示した実装がはるかに効率的です。はい、心配しないでください。連続した配列にすべてのものがあります。これは一例に過ぎません。 – GG1991

関連する問題