C ++将整数数组分成块

C++ split integer array into chunks

我想我的问题有两部分:

(1) 这是将数组的不同块发送到不同处理器的正确方法吗? 假设我有 n 个处理器,其等级范围从 0n-1。 我有一个大小为 d 的数组。我想将此数组拆分为 k 个大小相等的块。假设 d 可以被 k 整除。 我想将这些块中的每一个发送到等级小于 k 的处理器。 如果我可以使用 MPI_Scatter 之类的东西会很容易,但是这个函数会发送到所有其他处理器,而我只想发送到一定数量的 proc。 所以我所做的是我有一个 k 迭代循环并执行 k MPI_Isend。 这样有效率吗?

(2) 如果是,如何将数组拆分成块?总有简单的方法,那就是

int size = d/k;
int buffs[k][size];

for (int rank = 0; rank < k; ++rank)
{
    for (int i = 0; i < size ++i)
      buffs[rank][i] = input[rank*size + i];
    MPI_Isend(&buffs[rank], size, MPI_INT, rank, 1, comm, &request);
}

您正在寻找的是 MPI_Scatterv,它允许您明确指定每个块的长度及其相对于缓冲区开头的位置。如果您不想将数据发送到某些行列,只需将其块的长度设置为 0:

int blen[n];
MPI_Aint displ[n];

for (int rank = 0; rank < n; rank++)
{
    blen[rank] = (rank < k) ? size : 0;
    displ[rank] = rank * size;
}

int myrank;
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);

MPI_Scatterv(input, blen, displ, MPI_INT,
             mybuf, myrank < k ? size : 0, MPI_INT,
             0, MPI_COMM_WORLD);

请注意,对于 rank >= k,位移将 运行 超过缓冲区的末尾。没关系,因为 rank >= k 的块长度设置为零,并且不会访问任何数据。

至于您原来的方法,它不可移植,可能并不总是有效。原因是您正在覆盖相同的 request 句柄并且您从不等待发送完成。正确的实现是:

MPI_Request request[k];

for (int rank = 0; rank < k; ++rank)
{
    MPI_Isend(&input[rank*size], size, MPI_INT, rank, 1, comm, &request[rank]);
}
MPI_Waitall(k, request, MPI_STATUSES_IGNORE);

最佳实施方式是在子通信器中使用 MPI_Scatter

MPI_Comm subcomm;
MPI_Comm_split(MPI_COMM_WORLD, myrank < k ? 0 : MPI_UNDEFINED, myrank,
               &subcomm);
// Now there are k ranks in subcomm
// Perform the scatter in the subcommunicator
if (subcomm != MPI_COMM_NULL)
   MPI_Scatter(input, size, MPI_INT, mybuf, size, MPI_INT, 0, subcomm);

MPI_Comm_split 调用拆分 MPI_COMM_WORLD 并从所有小于 k 的原始等级创建一个新的通信器。它使用原始等级作为在新通信器中排序等级的关键字,因此 MPI_COMM_WORLD 中的等级 0 变为 subcomm 中的等级 0。由于 MPI_Scatter 通常比 MPI_Scatterv 表现更好,因此这是最佳解决方案。