概要:私はMPI_Type_create_struct()を使用して作成したデータ型が正しいことをテストしているため、正しい値が送信されます。私は配列に格納されている値を他のプロセッサに転送することに問題があります。私はこれがデータ型mpiboundを作成するために使用された配列のインデックス[]に格納されているオフセットと各構造体バインドの配列のメモリアドレスに問題があると考えます。MPI_Type_create_struct()を使用してC言語の動的配列を含む構造体を転送する
問題:私はMPIを使用しているプログラムに取り組んでいます。最終目標は、MPI_Gatherv()を使用して、以下に宣言されているboundという構造体の配列から値を収集することです。
struct bound {
int n;
char* name;
double* lat;
double* lon;
};
私はMPI_Type_create_struct()を正しく使用していることを確認するためのテストプログラムを作成しました。 MPI_Type_create_struct()を呼び出す関数を以下に記述します。
void CreateBoundType (struct bound a_bound) {
int blocklens[4]; /*Block Lengths of data in structure*/
MPI_Datatype old_types[4]; /*Data types of data in structure*/
MPI_Aint indices[4]; /*Byte displacement of each piece of data*/
MPI_Aint addr1, addr2, addr3, addr4, baseaddr;
/*Set block lengths*/
blocklens[0] = 1;
blocklens[1] = 10;
blocklens[2] = NPT_MAX;
blocklens[3] = NPT_MAX;
/*Set Data Types*/
old_types[0] = MPI_INT;
old_types[1] = MPI_CHAR;
old_types[2] = MPI_DOUBLE;
old_types[3] = MPI_DOUBLE;
/*Set byte displacement for each piece of data in structure*/
/*!!!!!I expect that the following 8 lines cause my problem!!!!!!*/
MPI_Get_address (&a_bound, &baseaddr);
MPI_Get_address (&a_bound.num_pts, &addr1);
MPI_Get_address (a_bound.label, &addr2);
MPI_Get_address (a_bound.lat, &addr3);
MPI_Get_address (a_bound.lon, &addr4);
indices[0] = addr1 - baseaddr;
indices[1] = addr2 - baseaddr;
indices[2] = addr3 - baseaddr;
indices[3] = addr4 - baseaddr;
/*Create structure type in MPI so that we can transfer boundaries between nodes*/
MPI_Type_create_struct(4,blocklens,indices,old_types,&mpibound);
MPI_Type_commit(&mpibound);
return;
}
私が使用するバッファ構造体の一部であるMPI_Bcast()アレイに記憶された値への呼び出しで、(グローバル変数、mpiboundある)私が作成したデータ型を使用しようとしますは更新されませんが、整数値n(nは配列の長さ)はすべてのプロセッサで変更されます。したがって、私の問題は、mpiboundを定義するために使用されるオフセット(インデックス[4])と関係していると思います。
以下、この関数をどのように呼び出して構造体を設定するかを示す主関数を書きました。 (私は私ができる限り短く、それを維持するためにMPI_Initおよび他のそのような関数への呼び出しを省いている)MPi_Bcastを呼び出した後、いくつかのprint文を置く
int main (int argc, char **argv) {
/*Initialise MPI etc*/...
/*Create structure to broadcast*/
struct bound my_bound;
my_bound.name = strdup(string);
my_bound.lat = malloc(NPT_MAX*sizeof(double));
my_bound.lon = malloc(NPT_MAX*sizeof(double));
if(rank == 0) {
my_bound.n = 5;
my_bound.lat[0] = 2.6;
my_bound.lon[0] = 4.2;
}
/*Call the function that creates the type mpibound*/
CreateBoundType(my_bound);
/*Create buffer to be used in a Broadcast from the root processor (rank 0)*/
struct bound *buff = malloc(sizeof(struct bound));
buff->lat = malloc(NPT_MAX*sizeof(double));
buff->lon = malloc(NPT_MAX*sizeof(double));
buff = &my_bound;
/*Cast values in buffer from proc 0 to all others*/
MPI_Bcast(buff,1,mpibound,0,MPI_COMM_WORLD);
/*Print values and checks, free memory etc*/...
return(EXIT_SUCCESS);
}
は示していランク> 0の値を持つprocsの上nはランク0からのブロードキャストに更新されますが、latとlonの配列の最初の要素はまだ0です。
私が大いに助けてくれれば幸いです。私はこれをできる限り短く保つように努めましたが、これは私が作成できる最高のバージョンです。
読んでいただきありがとうございます!
あなたのコードはほとんど意味がありません。あなたは2つの構造体と両方の配列のためのいくつかのメモリを割り当てますが、 'buff =&my_bound'を実行することで2番目の構造体のメモリを完全に捨てることができます。とにかく、適切な[mcve]とより具体的な予想と実際の出力を準備してください。 – Zulan
私は彼のコメントに@Zulanを返す。あなたのコードは間違いでいっぱいです。私はMPIの問題以上のものだと思っています。あなたがここで欠けているのはCの基本的な理解です。いったんC言語の基本が安定すれば、MPIに取り組もうとすることでレベルアップすることができますが、MPI + CでプログラミングするにはC言語が必須です。 – Gilles