使用具有自定义操作功能的 MPI reduceAll
Using MPI reduceAll with custom operation function
我正在尝试了解 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];
导致段错误,大概是因为试图访问大于数组大小的内容。
您最初的假设不正确。
在幕后,MPI 可能会使用各种优化技术来缩短消息并减少子数组。
一个可能的解决方法是使用派生数据类型(例如 2503 MPI_DOUBLE
的向量),更新用户定义的缩减,然后 MPI_Allgather()
为 count=1
。
MPI_Allreduce
被定义为对数组的各个元素进行并行操作(概念上,不是并发意义上的)。用户定义的操作有一个 len
参数是为了提高效率(通过函数指针和可能的向量化调用更少),正如您所看到的,实现可以将数组细分为任何方便大小的块。 (在这种情况下,它可能受到用于通信的缓冲区大小的限制。)
与 一样,您必须创建自己的数据类型以强制将数组视为一个单元。
我正在尝试了解 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];
导致段错误,大概是因为试图访问大于数组大小的内容。
您最初的假设不正确。
在幕后,MPI 可能会使用各种优化技术来缩短消息并减少子数组。
一个可能的解决方法是使用派生数据类型(例如 2503 MPI_DOUBLE
的向量),更新用户定义的缩减,然后 MPI_Allgather()
为 count=1
。
MPI_Allreduce
被定义为对数组的各个元素进行并行操作(概念上,不是并发意义上的)。用户定义的操作有一个 len
参数是为了提高效率(通过函数指针和可能的向量化调用更少),正如您所看到的,实现可以将数组细分为任何方便大小的块。 (在这种情况下,它可能受到用于通信的缓冲区大小的限制。)
与