MPI_Gather数量不等?

时间:2014-02-14 22:07:50

标签: c parallel-processing openmpi

我正在使用MPI_Scatter和MPI_Gather实现矩阵乘法。如果进程数均匀分为矩阵行数列,我的代码可以正常工作。但是,当它们没有均匀分配时,它会在MPI_Gather上崩溃。这是有道理的,因为MPI_Gather期望从每个进程获得一定数量,并且不会从最后一个进程获得那么多。有没有办法让这项工作?我查看了MPI_Gatherv,但我不希望数据之间有空格 - 我只是希望它收到的数量少于上一个进程的数量。

目前,我正在使用MPI_Scatter向每个进程发送以下数量:

ceil(N/size)

其中size是我正在使用的进程数,N是矩阵中的行数和列数。最后一个进程将不会收到与其他进程一样多的数据。当我到达最后一个进程中的数据末尾时,我确保停止进行乘法运算。如果无法更改我的MPI_Gather调用,我可以更改此分散+乘法部分。任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:0)

答案 1 :(得分:0)

我认为在辅助函数中包装MPI_ScattervMPI_Gatherv是可行的方法。今天我写了一对这样的包装作为我暑期学校的一部分,如果你还需要解决方案,请随意使用它们。

void fillCounts(int rank, int size, int totalCount, int *counts, int *offsets) {
    int i;
    int n;
    int sum;

    n = totalCount / size;
    for (i = 0; i < size; i++)
    counts[i] = n;

    for (i = 0; i < totalCount % size; i++)
        counts[i] += 1;

    sum = 0;
    for (i = 0; i < size; i++) {
    offsets[i] = sum;
    sum += counts[i];
    }
}

int scatter01(const void *sendBuf, int totalCount, MPI_Datatype dataType,
                    void *recvBuf, int *recvCount,
                    int root, MPI_Comm comm) {
    int rank;
    int size;
    int *counts;
    int *offsets;
    MPI_Comm_rank(comm, &rank);
    MPI_Comm_size(comm, &size);

    counts  = alloca(size * sizeof(int));
    offsets = alloca(size * sizeof(int));
    fillCounts(rank, size, totalCount, counts, offsets);

    *recvCount = counts[rank]; 
    return MPI_Scatterv(sendBuf, counts, offsets, dataType,
                        recvBuf, counts[rank, dataType, root, comm);
}

int gather01(void *recvBuf, int totalCount, MPI_Datatype dataType,
            const void *sendBuf, int root, MPI_Comm comm) {
    int rank;
    int size;
    int *counts;
    int *offsets;
    MPI_Comm_rank(comm, &rank);
    MPI_Comm_size(comm, &size);

    counts  = alloca(size * sizeof(int));
    offsets = alloca(size * sizeof(int));
    fillCounts(rank, size, totalCount, counts, offsets);

    return MPI_Gatherv(sendBuf, counts[rank], dataType,
               recvBuf, counts, offsets, dataType, root, comm);
}

用法示例:

double globData[N];
double partData[N/size+1];
int n;

scatter01(globData, N, MPI_DOUBLE, partData, &n, 0, MPI_COMM_WORLD);
gather01 (globData, N, MPI_DOUBLE, partData,     0, MPI_COMM_WORLD);

答案 2 :(得分:0)

MPI_Gather 用于从各个进程收集相同大小的信息。如果要收集的数组大小因进程而异,则应使用MPI_GatherV