gpt4 book ai didi

mpi - 关于 MPI_Scatter 执行器及其发送缓冲区分配的问题

转载 作者:行者123 更新时间:2023-12-03 07:49:18 35 4
gpt4 key购买 nike

我的第一个想法是MPI_Scatter并且应该在if(proc_id == 0)子句中使用发送缓冲区分配,因为数据应该只分散一次并且每次进程只需要发送缓冲区中的一部分数据,但它无法正常工作。

看来,在应用程序正常运行之前,所有进程都必须执行发送缓冲区分配和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 以及发送缓冲区定义和分配一起放入 if(proc_id == 0) 语句中。没有编译/运行时错误/警告,但其他进程的接收缓冲区没有收到其相应的部分数据。

最佳答案

你的问题不是很清楚,如果你展示一些你遇到问题的代码会更容易理解。这就是我认为你要问的——我只是猜测,因为这是我在 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;
}

为什么它不起作用,为什么会出现段错误?当然,其他进程无权访问数据;这就是重点。

答案是,在非根进程中,不使用 sendbuf 参数(MPI_Scatter() 的第一个参数)。因此,非根进程不需要需要访问数据。但是您仍然无法取消引用尚未定义的指针。因此,您需要确保所有 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)发出数据,所有接收者接收;每个参与的人都必须调用例程。分散是 MPI Collective Operation 的一个示例,其中通信器中的所有任务都必须调用相同的例程。其他示例包括广播、屏障、归约操作和收集操作。

如果只有进程 0 调用分散操作,您的程序将挂起,永远等待其他任务参与。

关于mpi - 关于 MPI_Scatter 执行器及其发送缓冲区分配的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5879496/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com