2011-07-06 57 views
2

MPI_Allgather()を使用してすべてのプロセスに構造体を送信する必要があります。私は明らかなエラーを出すようには思われませんが、コードは機能しません。 recv[]に値を受け取ったかどうかをチェックすると、何も表示されません。私が類似のコードを使って構造体の代わりに単一の変数を送信しただけであれば、何が起こっているのか分かりません。構造体には静的配列があるため、メモリは連続している必要がありますか、MPI_Packなどを使用する必要がありますか?コードは次のとおりです。MPI_Allgatherを使用して構造体を配布する

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

#define NUMEL 21 
struct mystruct{ 
int sendarray[10]; 
int a; 
char array2[10]; 
}; 

typedef struct mystruct struct_t; 

int main (int argc, char ** argv) 
{ 
MPI_Status status; 
int rank, size; 
char *recv; 
int i, j; 
MPI_Init(&argc, &argv); 
MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
MPI_Comm_size(MPI_COMM_WORLD, &size); 
// init 
struct_t * fd = (struct_t*)malloc(sizeof(*fd));; 
for (i=0;i<10;i++){ 
    fd->sendarray[i] = 0; 
    fd->array2[i] = 0; 
} 
recv = (char *) malloc (size*NUMEL); 

// put some stuff in your array 
for (i=0;i<size;i++){ 
    if(rank == i){ 
     fd->sendarray[i] = i *10; 
     fd->array2[i] = i *20; 
     fd->a = rank; 
    } 
    if(fd->sendarray[i] != 0) 
    printf("My rank is %d, fd->sendarray[%d] is %d\n", rank, i, fd->sendarray[i]); 
    } 

    // gather data from all now.. 
    MPI_Allgather (fd, NUMEL, MPI_BYTE, recv, NUMEL * size, MPI_INT, MPI_COMM_WORLD); 

    // check if correct data has been received 
    for (i=0;i<size*NUMEL;i++){ 
    if(recv[i] != 0) 
    printf("My rank is %d and recv[i]=%d and i is %d\n", rank, recv[i],i); 
    } 
MPI_Finalize(); 
} 

答えて

9

Allgatherは初めて見るときに少し混乱することがあります。ここにはいくつかのことがあります。

まず、allgatherするカウント - 送信回数とのrecvカウントは - 各プロセスでを送信されるデータの量であり、各プロセスからを受け取りました。

第2に、allgatherの仕組みは、送信されたデータを連結することです。あなたはこのように見て、各プロセスに送信アレイと

int send[3]; 
int recv[9]; 

を持っているのであれば:

recv: 
     +---+---+---+---+---+---+---+---+---+ 
     | 0 | 0 | 0 | 1 | 1 | 1 | 2 | 2 | 2 |  
     +---+---+---+---+---+---+---+---+---+ 

send: 
     +---+---+---+ 
     | 0 | 0 | 0 |  rank 0 
     +---+---+---+ 

     +---+---+---+ 
     | 1 | 1 | 1 |  rank 1 
     +---+---+---+ 

     +---+---+---+ 
     | 2 | 2 | 2 |  rank 2 
     +---+---+---+ 

その後

MPI_Allgather(send, 3, MPI_INT, recv, 3, MPI_INT, MPI_COMM_WORLD); 

への呼び出しがもたらすであろう

コードのバージョン正しいデータを引き出す:

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

struct mystruct{ 
    int sendarray[10]; 
    int a; 
    char array2[10]; 
}; 

typedef struct mystruct struct_t; 

int main (int argc, char ** argv) 
{ 
    int rank, size; 
    struct_t *recv; 
    int i, j; 
    MPI_Init(&argc, &argv); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &size); 
    // init 
    struct_t * fd = (struct_t*)malloc(sizeof(*fd)); 
    for (i=0;i<10;i++){ 
     fd->sendarray[i] = 0; 
     fd->array2[i] = 0; 
    } 
    recv = malloc (size * sizeof(*fd)); 

    // put some stuff in your array 
    fd->sendarray[rank] = rank*10; 
    fd->array2[rank] = rank*20; 
    fd->a = rank; 
    printf("My rank is %d, fd->sendarray[%d] is %d\n", rank, i, fd->sendarray[i]); 

    // gather data from all now.. 
    MPI_Allgather (fd, sizeof(*fd), MPI_BYTE, recv, sizeof(*fd), MPI_BYTE, MPI_COMM_WORLD); 


    // check if correct data has been received 
    if (rank == 0) { 
     printf("Received:\n"); 
     for (i=0;i<size;i++){ 
      printf("---\n"); 
      printf("int array: "); 
      for (j=0; j<10; j++) printf("%3d ", recv[i].sendarray[j]); 
      printf("\nint:  "); printf("%3d\n", recv[i].a); 
      printf("char array: "); 
      for (j=0; j<10; j++) printf("%3d ", (int)(recv[i].array2[j])); 
      printf("\n"); 
     } 
    } 
    MPI_Finalize(); 
    return 0; 
} 

これらの構造体は、それらの構造体の配列に相当するものに集約されます。 4つのプロセッサと実行すると得られます。

My rank is 0, fd->sendarray[10] is 0 
My rank is 1, fd->sendarray[10] is 1 
My rank is 2, fd->sendarray[10] is 2 
My rank is 3, fd->sendarray[10] is 3 

Received: 
--- 
int array: 0 0 0 0 0 0 0 0 0 0 
int:   0 
char array: 0 0 0 0 0 0 0 0 0 0 
--- 
int array: 0 10 0 0 0 0 0 0 0 0 
int:   1 
char array: 0 20 0 0 0 0 0 0 0 0 
--- 
int array: 0 0 20 0 0 0 0 0 0 0 
int:   2 
char array: 0 0 40 0 0 0 0 0 0 0 
--- 
int array: 0 0 0 30 0 0 0 0 0 0 
int:   3 
char array: 0 0 0 60 0 0 0 0 0 0 

あなたが本当に集まっただけで対応する要素をしたい場合は、あなたは、単に構造で、その特定の場所から1つのint型/文字を送信したい:

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

struct mystruct{ 
    int sendarray[10]; 
    int a; 
    char array2[10]; 
}; 

typedef struct mystruct struct_t; 

int main (int argc, char ** argv) 
{ 
    int rank, size; 
    struct_t fd; 
    struct_t recv; 
    int i, j; 
    MPI_Init(&argc, &argv); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &size); 
    // init 
    for (i=0;i<10;i++){ 
     fd.sendarray[i] = 0; 
     fd.array2[i] = 0; 

     recv.sendarray[i] =999; 
     recv.array2[i] = 99; 
    } 
    recv.a =999; 

    // put some stuff in your array 
    fd.sendarray[rank] = rank*10; 
    fd.array2[rank] = (char)(rank*20); 
    fd.a = rank; 
    printf("My rank is %d, fd.sendarray[%d] is %d\n", rank, rank, fd.sendarray[rank]); 

    // gather data from all now.. send the int: 
    MPI_Allgather (&(fd.sendarray[rank]), 1, MPI_INT, recv.sendarray, 1, MPI_INT, MPI_COMM_WORLD); 
    // then the char 
    MPI_Allgather (&(fd.array2[rank]), 1, MPI_CHAR, recv.array2, 1, MPI_CHAR, MPI_COMM_WORLD); 

    // check if correct data has been received 
    if (rank == 0) { 
     printf("Received:\n"); 
     printf("---\n"); 
     printf("int array: "); 
     for (j=0; j<10; j++) printf("%3d ", recv.sendarray[j]); 
     printf("\nint:  "); printf("%3d\n", recv.a); 
     printf("char array: "); 
     for (j=0; j<10; j++) printf("%3d ", (int)(recv.array2[j])); 
     printf("\n"); 
    } 
    MPI_Finalize(); 

    return 0; 
} 

を我々場合これを4つのプロセスで実行すると、次のようになります。

My rank is 0, fd.sendarray[0] is 0 
My rank is 1, fd.sendarray[1] is 10 
My rank is 2, fd.sendarray[2] is 20 
My rank is 3, fd.sendarray[3] is 30 
Received: 
--- 
int array: 0 10 20 30 999 999 999 999 999 999 
int:  999 
char array: 0 20 40 60 99 99 99 99 99 99 
+2

ありがとう!これは非常に役に立ちました! – lostinpointers

関連する問題