相当于MPI_Reduce_scatter但在处理器子集中散布

时间:2014-06-18 21:34:58

标签: mpi

是否有一个等同于MPI_Reduce_scatter的MPI函数,它只在一部分处理器中执行散射?如果没有这样的功能,这是最有效的MPI呼叫序列?


为清楚起见,假设reduce操作是总和。 来自

proc    sendbuf
1       a1 | b1
2       a2 | b2
3       a3 | b3
4       a4 | b4 

我想要

proc    recvbuf
1       a
2       b
3       
4       

a = a1 + a2 + a3 + a4b = b1 + b2 + b3 + b4


变通方法

  • 使用两个MPI_Reduce。第一个减少a并且有1个作为根处理器。第二个减少b s并且有2个作为根处理器。但是,当有很多字母时会变得很重。 (和许多处理器)。
  • MPI_Reduce_scatter并且仅当recv_count[proc]属于处理器子集时才设置proc与零不同。但是,在散布消息时,会有n_proc个方形握手(大多数都没用,因为实际上没有发送消息)。

2 个答案:

答案 0 :(得分:1)

我同意,如果你希望MPI为你做(你可能会做大规模的),那么两个MPI_REDUCE电话可能会和你一样好。

答案 1 :(得分:1)

你可能会过度思考 - 在上面的例子中,你可以用一个reduce和一个send / recv对来做到这一点:

#include <stdio.h>
#include <mpi.h>

int main(int argc, char **argv) {

    int data[2], result[2];
    int rank, size;
    const int amaster=0, bmaster=1;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    data[0] = 2*rank;
    data[1] = 3*rank;

    MPI_Reduce(data, result, 2, MPI_INT, MPI_SUM, amaster, MPI_COMM_WORLD);
    if (rank == amaster) {
        int tota = result[0];
        printf("%d: Total a = %d, expected = %d\n", rank, tota, 2*size*(size-1)/2);
        MPI_Send(&(result[1]), 1, MPI_INT, bmaster, 0, MPI_COMM_WORLD);
    }
    if (rank == bmaster) {
        int totb;
        MPI_Recv(&totb, 1, MPI_INT, amaster, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        printf("%d: Total b = %d, expected = %d\n", rank, totb, 3*size*(size-1)/2);
    }

    MPI_Finalize();
    return 0;
}

多个数据的自然概括是分散的,所以你对MPI_Reduce_scatter的直觉是正确的,但是这里因为两组任务重叠(所以你不能使用一个内部通信器)但不是同样,你必须做一个减少后跟散点图,散点图必须在另一个传播者身上:

#include <stdio.h>
#include <mpi.h>

int main(int argc, char **argv) {

    const int ndata = 5;
    int data[ndata], result[ndata];
    int rank, size;
    const int amaster=0;
    MPI_Comm  scattercomm;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    if (size < ndata) {
        if (rank == 0) fprintf(stderr,"Too few ranks; exiting\n");
        MPI_Abort(MPI_COMM_WORLD,1);
    }

    for (int i=0; i<ndata; i++)
        data[i] = (i+2)*rank;

    /* create scatter communicator; all  of comm world must participate */
    MPI_Group basegrp, scattergrp;

    MPI_Comm_group(MPI_COMM_WORLD, &basegrp);

    int mpiranks[ndata];
    for (int i=0; i<ndata; i++)
        mpiranks[i] = i;

    MPI_Group_incl(basegrp, ndata, mpiranks, &scattergrp);
    MPI_Comm_create(MPI_COMM_WORLD, scattergrp, &scattercomm);

    MPI_Reduce(data, result, ndata, MPI_INT, MPI_SUM, amaster, MPI_COMM_WORLD);
    if (rank < ndata) {
        int item;
        MPI_Scatter(result, 1, MPI_INT, &item, 1, MPI_INT, amaster, scattercomm);

        printf("%d: Total = %d, expected = %d\n", rank, item, (rank+2)*size*(size-1)/2);
    }

    MPI_Finalize();
    return 0;
}