MPI发送/接收数百万条消息
对于大于0的进程,我有一个NT循环(数百万次迭代)。对于每次迭代,120字节的消息被发送到proc0,proc0接收它们(对于proc0,我在NT上有相同的循环) 我希望proc 0接收订购的数据,以便将它们存储在数组nhdr1中 问题是proc0不能正确地接收消息,我在数组nhdr中经常有0个值 如何修改代码,使消息的接收顺序与发送顺序相同MPI发送/接收数百万条消息,mpi,Mpi,对于大于0的进程,我有一个NT循环(数百万次迭代)。对于每次迭代,120字节的消息被发送到proc0,proc0接收它们(对于proc0,我在NT上有相同的循环) 我希望proc 0接收订购的数据,以便将它们存储在数组nhdr1中 问题是proc0不能正确地接收消息,我在数组nhdr中经常有0个值 如何修改代码,使消息的接收顺序与发送顺序相同 [...] if (rank == 0) { nhdr = malloc((unsigned long)15*sizeof(*
[...]
if (rank == 0) {
nhdr = malloc((unsigned long)15*sizeof(*nhdr));
nhdr1 = malloc((unsigned long)NN*15*sizeof(*nhdr1));
itr = 0;
jnode = 1;
for (l=0; l<NT; l++) {
MPI_Recv(nhdr, 15, MPI_LONG, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
if (l == status.MPI_TAG) {
for (i=0; i<nkeys; i++)
nhdr1[itr*15+i] = nhdr[i];
}
itr++;
if (itr == NN) {
ipos = (unsigned long)(jnode-1)*NN*15*sizeof(*nhdr1);
fseek(ismfh, ipos, SEEK_SET);
nwrite += fwrite(nhdr1, sizeof(*nhdr1), NN*15, ismfh);
itr = 0;
jnode++;
}
}
free(nhdr);
free(nhdr1);
} else {
nhdr = malloc(15*sizeof(*nhdr));
irecmin = (rank-1)*NN+1;
irecmax = rank*NN;
for (l=0; l<NT; l++) {
if (jrec[l] >= irecmin && jrec[l] <= irecmax) {
indx1 = (unsigned long)(jrec[l]-irecmin) * 15;
for (i=0; i<15; i++)
nhdr[i] = nhdr1[indx1+i]; // nhdr1 is allocated before for rank>0!
MPI_Send(nhdr, 15, MPI_LONG, 0, l, MPI_COMM_WORLD);
}
}
free(nhdr);
}
[…]
如果(秩==0){
nhdr=malloc((无符号长)15*sizeof(*nhdr));
nhdr1=malloc((无符号长)NN*15*sizeof(*nhdr1));
itr=0;
jnode=1;
对于(l=0;l无法保证您的消息将以从不同级别发送的相同顺序到达级别0。例如,如果您有这样的场景(S1
表示发送消息1):
无法保证消息将以S1、S2、S3、S4的顺序到达秩0。MPI提供的唯一保证是,在具有相同标记(您正在执行)的同一通信器上发送的每个秩的消息将以其发送的相同顺序到达。这意味着产生的顺序可能是:
S1, S2, S3, S4
S1, S3, S2, S4
或者可以是:
S1, S2, S3, S4
S1, S3, S2, S4
或:
……等等
对于大多数应用程序来说,这并不重要。重要的顺序是逻辑顺序,而不是实时顺序。您可以再看一看应用程序,确保您的要求不会有丝毫的放松。无法保证您的消息将以与发送时相同的顺序到达0级来自不同级别。例如,如果您有这样的场景(S1
表示发送消息1):
无法保证消息将以S1、S2、S3、S4的顺序到达秩0。MPI提供的唯一保证是,在具有相同标记(您正在执行)的同一通信器上发送的每个秩的消息将以其发送的相同顺序到达。这意味着产生的顺序可能是:
S1, S2, S3, S4
S1, S3, S2, S4
或者可以是:
S1, S2, S3, S4
S1, S3, S2, S4
或:
……等等
对于大多数应用程序来说,这并不重要。重要的顺序是逻辑顺序,而不是实时顺序。您可以再看一看您的应用程序,确保您的要求不会有丝毫的放松。您所说的“消息接收的顺序与发送的顺序相同”是什么意思
在现在的代码中,消息的接收顺序(大致)与它们实际发送的顺序相同……但该顺序与排名数字无关,或者与其他任何事情无关。有关更多信息,请参阅@Wesley Bland的回复
如果您的意思是“按排名顺序接收消息”…那么有几个选项
首先,像MPI_Gather或MPI_Gatherv这样的集合将是一个“明显”的选择,以确保数据按产生数据的列组排序。这仅在每个列组进行相同次数的迭代,并且这些迭代保持大致同步时才有效
其次,您可以删除任何源的MPI\u,并发布一组MPI\u IRevc,其中缓冲区按“顺序”提供。当消息到达时,它将“自动”位于正确的缓冲区位置对于接收到的每条消息,可以使用提供的正确recv缓冲区位置发布新的MPI_Irecv。任何不匹配的MPI_Irecv都需要在作业结束时取消。您所说的“消息接收顺序与发送顺序相同”是什么意思
在现在的代码中,消息的接收顺序(大致)与它们实际发送的顺序相同……但该顺序与排名数字无关,或者与其他任何事情无关。有关更多信息,请参阅@Wesley Bland的回复
如果您的意思是“按排名顺序接收消息”…那么有几个选项
首先,像MPI_Gather或MPI_Gatherv这样的集合将是一个“明显”的选择,以确保数据按产生数据的列组排序。这仅在每个列组进行相同次数的迭代,并且这些迭代保持大致同步时才有效
其次,您可以删除任何源的MPI\u,并发布一组MPI\u IRevc,其中缓冲区按“顺序”提供。当消息到达时,它将“自动”位于正确的缓冲区位置对于接收到的每条消息,可以使用提供的正确recv缓冲区位置发布新的MPI\u Irecv。任何不匹配的MPI\u Irecv都需要在作业结束时取消。请记住:
- 按顺序和顺序接收来自给定列组的消息
- 消息在MPI_Recv()返回的状态结构()中具有原始处理器秩
您可以使用这两个元素将接收到的数据正确地放入nhdr1。请记住:
- 按顺序和顺序接收来自给定列组的消息
- 消息在MPI_Recv()返回的状态结构()中具有原始处理器秩
您可以使用这两个元素将接收到的数据正确地放入nhdr1中