我的第一个想法是MPI_Scatter
,并且应该在if(proc_id == 0)
子句中使用send-buffer allocation,因为数据应该只被分散一次,每个进程只需要发送缓冲区中的一部分数据,但它无法正常工作。
在应用程序正常运行之前,似乎所有进程都必须执行发送缓冲区分配和MPI_Scatter
。
所以我徘徊,MPI_Scatter
存在的哲学是什么,因为所有进程都可以访问发送缓冲区。
任何帮助都将不胜感激。
<小时/> 修改 我写的代码是这样的:
if (proc_id == 0) {
int * data = (int *)malloc(size*sizeof(int) * proc_size * recv_size);
for (int i = 0; i < proc_size * recv_size; i++) data[i] = i;
ierr = MPI_Scatter(&(data[0]), recv_size, MPI_INT, &recievedata, recv_size, MPI_INT, 0, MPI_COMM_WORLD);
}
我认为,这足以让根进程分散数据,其他进程需要做的就是接收数据。所以我把MPI_Scatter
和发送缓冲区定义&amp;分配,在if(proc_id == 0)
语句中。没有编译/运行时错误/警告,但其他进程的接收缓冲区没有收到相应的数据部分。
答案 0 :(得分:4)
您的问题不是很明确,如果您展示了一些您遇到问题的代码,那么问题会更容易理解。这就是我所想的你想要的 - 而我只是猜测这是因为这是一个错误,我看到有人在C制作中对MPI不熟悉。
如果你有这样的代码:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int main(int argc, char **argv) {
int proc_id, size, ierr;
int *data;
int recievedata;
ierr = MPI_Init(&argc, &argv);
ierr|= MPI_Comm_size(MPI_COMM_WORLD,&size);
ierr|= MPI_Comm_rank(MPI_COMM_WORLD,&proc_id);
if (proc_id == 0) {
data = (int *)malloc(size*sizeof(int));
for (int i=0; i<size; i++) data[i] = i;
}
ierr = MPI_Scatter(&(data[0]), 1, MPI_INT,
&recievedata, 1, MPI_INT, 0, MPI_COMM_WORLD);
printf("Rank %d recieved <%d>\n", proc_id, recievedata);
if (proc_id == 0) free(data);
ierr = MPI_Finalize();
return 0;
}
为什么它不起作用,为什么会出现分段错误? 当然其他进程无法访问data
;这就是重点。
答案是在非根进程中,不使用sendbuf
参数(MPI_Scatter()
的第一个参数)。因此,非根进程不需要访问data
。但你仍然无法解除引用你没有定义的指针。因此,您需要确保所有C代码都有效。但是在所有其他进程中,数据可以是NULL或完全未定义;你必须确保你不会意外地解除引用它。所以这很好用,例如:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int main(int argc, char **argv) {
int proc_id, size, ierr;
int *data;
int recievedata;
ierr = MPI_Init(&argc, &argv);
ierr|= MPI_Comm_size(MPI_COMM_WORLD,&size);
ierr|= MPI_Comm_rank(MPI_COMM_WORLD,&proc_id);
if (proc_id == 0) {
data = (int *)malloc(size*sizeof(int));
for (int i=0; i<size; i++) data[i] = i;
} else {
data = NULL;
}
ierr = MPI_Scatter(data, 1, MPI_INT,
&recievedata, 1, MPI_INT, 0, MPI_COMM_WORLD);
printf("Rank %d recieved <%d>\n", proc_id, recievedata);
if (proc_id == 0) free(data);
ierr = MPI_Finalize();
return 0;
}
如果你在C中使用“多维数组”,并且说散布一行矩阵,那么你必须跳过一两个额外的箍来使这个工作,但它仍然很容易。
<强>更新强>
请注意,在上面的代码中,所有例程都称为Scatter
- 发件人和收件人。 (实际上,发件人也是接收者)。
在消息传递范例中,发送方和接收方都必须合作发送数据。原则上,这些任务可能位于不同的计算机上,可能位于不同的建筑物中 - 它们之间没有任何共享。因此,任务1无法将数据“放入”任务2内存的某些部分。 (请注意,MPI2具有“单面消息”,但即使这样也需要发送方和接收方之间有很大程度的协调,因为必须有一个窗口可以将数据推入或拉出数据。)
这个典型的例子是发送/接收对; (比方说)进程0向进程3发送数据是不够的,进程3也必须接收数据。
MPI_Scatter
函数包含发送和接收逻辑。根进程(此处指定为0)发送数据,并且所有接收者都接收到;参与的每个人都必须打电话给例程。 Scatter是MPI Collective Operation的一个示例,其中通信器中的所有任务都必须调用相同的例程。广播,屏障,减少操作和收集操作是其他例子。
如果您只有进程0调用分散操作,您的程序将挂起,等待其他任务参与。