你的问题不是很清楚,如果你展示一些你遇到问题的代码会更容易理解。这就是我的think你问的问题——我只是猜测这一点,因为这是我在 C make 中看到 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;
}
为什么它不起作用,为什么会出现分段错误?的course其他进程无权访问data
;这就是重点。
答案是,在非 root 进程中,sendbuf
参数(第一个参数MPI_Scatter()
) 没有被使用。所以非根进程don't需要访问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 中使用“多维数组”,并说分散矩阵的一行,那么您必须跳过一两个额外的环才能完成这项工作,但这仍然很容易。
Update:
请注意,在上面的代码中,所有例程都调用Scatter
- 发送者和接收者。 (实际上,发送者也是接收者)。
在消息传递范例中,发送者和接收者都必须合作才能发送数据。原则上,这些任务可以在不同的计算机上进行,也可能位于不同的建筑物中——它们之间不共享任何内容。因此,任务 1 无法将数据“放入”任务 2 内存的某些部分。 (请注意,MPI2 具有“单向消息”,但即便如此,也需要发送方和接收方之间进行高度协调,因为必须留出一个窗口来将数据推入或拉出数据)。
典型的例子是发送/接收对;进程 0 向进程 3 发送数据是不够的,进程 3 还必须接收数据。
The MPI_Scatter
函数包含发送和接收逻辑。根进程(这里指定为0)发出数据,所有接收者接收;每个参与的人都必须调用例程。散点图是一个例子MPI 集体运营,其中通信器中的所有任务都必须调用相同的例程。其他示例包括广播、屏障、归约操作和收集操作。
如果只有进程 0 调用分散操作,您的程序将挂起,永远等待其他任务参与。