gpt4 book ai didi

c++ - 我发现自己无法理解 MPI_Gatherv 的参数 "recvcounts"

转载 作者:行者123 更新时间:2023-11-30 04:32:39 26 4
gpt4 key购买 nike

MPI_Gatherv 是 MPI 的接口(interface),如下所示:

int MPI_Gatherv(
void* sendbuf,
int sendcount,
MPI_Datatype sendtype,
void* recvbuf,
int *recvcounts,
int *displs,
MPI_Datatype recvtype,
int root,
MPI_Comm comm)

“recvcounts”的类型是“int *”,这样我们就可以分别设置每个进程要接收的元素的数量;但是我发现这是不可能实现的:

当recvcounts[i] < sendcount时,根进程将只接收sendcount项;

当recvcounts[i] > sendcount时,程序会崩溃,错误信息是这样的:

Fatal error in PMPI_Gatherv: Message truncated, error stack:
PMPI_Gatherv(386).....: MPI_Gatherv failed(sbuf=0012FD34, scount=2, MPI_CHAR, rbuf=0012FCC8, rcnts=0012FB30, displs=0012F998, MPI_CHAR, root=0, MPI_COMM_WORLD) failed
MPIR_Gatherv_impl(199):
MPIR_Gatherv(103).....:
MPIR_Localcopy(332)...: Message truncated; 2 bytes received but buffer size is 1

所以这意味着 root 必须从每个进程接收固定数量的项目并且参数 recvcount 没有意义?还是我误解了什么?

这是我的代码:

#include <mpi.h>
#include <iostream>

int main(int argc, char* argv[])
{
MPI_Init(&argc, &argv);

int n, id;
MPI_Comm_size(MPI_COMM_WORLD, &n);
MPI_Comm_rank(MPI_COMM_WORLD, &id);

char x[100], y[100];
memset(x, '0' + id, sizeof(x));
memset(y, '%', sizeof(y));
int cnts[100], offs[100] = {0};
for (int i = 0; i < n; i++)
{
cnts[i] = i + 1;
if (i > 0)
{
offs[i] = offs[i - 1] + cnts[i - 1];
}
}
MPI_Gatherv(x, 1, MPI_CHAR, y, cnts, offs, MPI_CHAR, 0, MPI_COMM_WORLD); // receive only 1 item from each process
//MPI_Gatherv(x, 2, MPI_CHAR, y, cnts, offs, MPI_CHAR, 0, MPI_COMM_WORLD); // crash
if (id == 0)
{
printf("Gatherv:\n");
for (int i = 0; i < 100; i++)
{
printf("%c ", y[i]);
}
printf("\n");
}

MPI_Finalize();

return 0;
}

最佳答案

正如@Alexander Molodih 指出的那样,sendcount=recvcount、sendtype=recvtype 将始终有效;但是当您开始创建自己的 MPI 类型时,您通常会有不同的发送和接收类型,这就是 recvcount 可能与 sendcount 不同的原因。

例如,看看最近问的 MPI partition matrix into blocks ;有一个二维数组被分解成 block 并分散。发送类型(只需要从全局数组中取出必要的数据)和接收类型(只是一个连续的数据 block )不同,计数也是不同的。

这就是发送和接收类型和计数不同的一般原因,例如 sendrecv、收集/分散或任何其他同时发生发送和接收的操作。

在您的 gatherv 情况下,每个进程可能有自己不同的发送计数,但 recvcount[] 数组必须是所有这些计数的列表,以便接收方可以正确放置接收到的数据。如果您事先不知道这些值,(每个等级只知道自己的计数,cnts[id])您可以先进行收集:

MPI_Gather(&(cnts[id]), 1, MPI_INT, cnts, 1, MPI_INT, 0, MPI_COMM_WORLD):
for (int i = 1; i < n; i++) {
offs[i] = offs[i - 1] + cnts[i - 1];
}
MPI_Gatherv(x, cnts[id], MPI_CHAR, y, cnts, offs, MPI_CHAR, 0, MPI_COMM_WORLD);

关于c++ - 我发现自己无法理解 MPI_Gatherv 的参数 "recvcounts",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7495714/

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