使用MPI reduceAll具有自定义操作功能

时间:2018-01-06 00:34:08

标签: c mpi

我试图了解reduceAll MPI函数的用法。

在我的主项目中,我有一个数组,每个进程处理数组的一部分,然后在每个进程之后,传递它们的结果,形成新的数组,让程序重复。

因此,对于这个基本示例,我只需要一个大小为2503的数组,并让每个MPI进程在数组中的不同位置存储一些硬编码数字。然后在reduceAll之后得到一个大小为2503的数组,但是最后一个位置[2502]中的值会从最初输入的值改变。

#include <mpi.h>
#include <math.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>

void stitchResultArrays(double *in, double *inout, int *len){
    printf("0= %f\n", in[0]);
    printf("out1= %f\n", inout[0]);
    printf("out1= %f\n", inout[1]);
    printf("1= %f\n", in[1]);
    printf("len = %d\n", *len);

    inout[2502] += in[2502];
}

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

    // Get the number of processes
    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);
    int arraySize = 50;

    double sendMpiMessage[2503];
    double test[2503];

    // Get the rank of the process
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);

    printf("size = %d\n", (arraySize * arraySize) + 3);
    sendMpiMessage[2502]= 4.1;
    sendMpiMessage[2501] = 4.4;
    sendMpiMessage[2500] = 4.2;

    sendMpiMessage[0] = 4.5;
    sendMpiMessage[1] = (double) (world_rank + 5);

    MPI_Op stitchResultArraysOp;
    MPI_Op_create((MPI_User_function *)stitchResultArrays, 1, &stitchResultArraysOp);

    printf("------");
    MPI_Allreduce(sendMpiMessage, test, 2503, MPI_DOUBLE, stitchResultArraysOp, MPI_COMM_WORLD);

    printf("result = %f\n", test[2502]);

    MPI_Finalize();

    return 0;
}

在这个例子中,我假设reduceAll函数内部的长度大小为2503(与数组大小相同),但是看起来* len在一个进程中是1251而在另一个进程中是1252我不确定为什么会这样呢?

结果,这似乎是我的行动:

inout[2502] += in[2502];

导致段错误,大概是为了尝试访问大于数组大小的东西。

2 个答案:

答案 0 :(得分:3)

MPI_Allreduce被定义为在数组的各个元素上并行(概念上,不是并发意义上)。用户定义的操作具有len参数用于提高效率(通过函数指针和可能的向量化调用的次数较少),并且如您所见,实现可以将数组细分为任何方便大小的块。 (在这种情况下,它可能受到用于通信的缓冲区大小的限制。)

作为Gilles said,您必须创建自己的数据类型以强制将数组视为一个单元。

答案 1 :(得分:2)

您的初步假设不正确。

在幕后,MPI可能会使用各种优化技术,从而缩短消息并减少子阵列。

可能的解决方法是使用派生数据类型(例如2503 seda <- function(x, y, z){ is.v <- function(...) lengths(list(...)) > 1 if(is.v(match.call())) stop("Error") # instead of `is.v(x, y, z)` x + y + z } seda(2, 2, 3) seda(c(2, 3), 2, 3) 的向量),更新用户定义的缩减,然后使用MPI_DOUBLE更新MPI_Allgather()