2017-06-22 55 views
0

我有np進程和np不同長度的數組。我必須將其中的一個發送給每個人(對所有進程重複相同)。其中一個np部件應該保持在這個過程中。在每個進程上收集不同長度的數組

在3個處理的情況下應該是:

p0具有[A0 B0 C0]並且應該終於有[A0 A1 A2]

p1具有[A1 B1 C1]並且應該終於有[B0 B1 B2]

p2具有[A2 B2 C2]並且應該終於有[C0 C1 C2]

我的想法是,首先收集所有的長度,然後分配內存,最後做一個MPI_gatherv操作在同一時間更改根排名像共享信息:

#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; 
} 

有沒有更好的方法或高效的內置功能可以執行此操作?

回答

2

首先,您可以使用MPI_Allgather而不是MPI_Gather循環來分配長度。

然後,你描述的操作是MPI_Alltoall操作:

illustration of All_gather/Alltoall

然而,在不同的變量具有數據複雜的事情。您可以使用一些MPI_Bottom/type voodoo,但我寧願推薦將不同級別的數據放在一個連續的陣列中 - 然後使用MPI_Alltoallv來分配它。

+0

非常感謝你Zulan!這就是我一直在尋找的!當然,我展示的實現更有效率。是的,別擔心我在連續陣列上有所有事情。這只是一個例子。 – GG1991

相關問題