C ++将整数数组拆分成块

时间:2015-03-24 04:24:18

标签: c++ arrays algorithm parallel-processing mpi

我想我的问题有两部分:

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

(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);
}

1 个答案:

答案 0 :(得分:1)

您正在寻找的是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,因此这是最佳解决方案。