MPI_Reduce C/C++ - 信号:分段错误 (11)

MPI_Reduce C/C++ - Signal: Segmentation Fault (11)

我不太了解 MPI_Reduce 如何与数组一起使用。 我需要做一个元素明智的总和。

为了测试 MPI_Reduce 函数,我编写了这个简单的代码并且它有效:

double a[4] = {0,1,2,(double)process_id};
double b[4];
MPI_Reduce(&a, &b, 4, MPI_DOUBLE, MPI_SUM, p-1, MPI_COMM_WORLD);
if(id == p-1) {
    for(int i = 0; i < 4; i++){
        printf("%f, ", b[i]);
    }
}

它打印这个:

0.00000, 4.00000, 8.00000, 6.00000 

当我 运行 此代码有 4 个进程时。有效!

现在我实施我的问题。假设我使用 p 过程,我需要减少维度 m * np 矩阵,所以我以数组

的形式重写每个矩阵
double *a;
double **A;

A = new double*[n];
//code that compute matrix A
a = (double *) malloc(m * n * sizeof(double));
int k = 0;
for(int i = 0; i < m; i++) {
    for(int j = 0; j < n; j++){
        a[k] = A[i][j];
        k++;
    }
}

这样我就得到了我需要以数组形式减少的矩阵。现在我执行这个减少:

if(id == p-1){
    reduce_storage = (double *) malloc(m * n * sizeof(double));
}

MPI_Reduce(&a, &reduce_storage, m * n, MPI_DOUBLE, MPI_SUM, p-1, MPI_COMM_WORLD);

数组 areduce_storage 以相同的方式分配,因此它们具有相同的维度 m * n, count 个参数的值 MPI_Reduce。我不明白为什么我尝试 运行 它 return 这个错误:

*** stack smashing detected ***: <unknown> terminated
[EdoardoPC:01104] *** Process received signal ***
[EdoardoPC:01104] Signal: Aborted (6)
[EdoardoPC:01104] Signal code:  (-6)
[EdoardoPC:01104] *** Process received signal ***
[EdoardoPC:01104] Signal: Segmentation fault (11)
[EdoardoPC:01104] Signal code:  (128)
[EdoardoPC:01104] Failing at address: (nil)

I don't understand well how the MPI_Reduce works with array. I need to do an element wise sum.

来自source 关于MPI_Reduce 可以阅读:

Reduces values on all processes to a single value

int MPI_Reduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm)

在您的情况下 MPI_Reduce 将如下图所示工作:

(图片取自https://mpitutorial.com/tutorials/mpi-reduce-and-allreduce/

从同一来源可以阅读:

MPI_Reduce takes an array of input elements on each process and returns an array of output elements to the root process. The output elements contain the reduced result.

现在让我们看看你的问题

To test the MPI_Reduce function I write this simple code and it works:

double a[4] = {0,1,2,(double)process_id};
double b[4];
MPI_Reduce(&a, &b, 4, MPI_DOUBLE, MPI_SUM, p-1, MPI_COMM_WORLD);

参数全部正确; &a&b 分别匹配 const void *sendbufvoid *recvbuf。这同样适用于其余参数,即 intMPI_DatatypeMPI_OpintMPI_Comm.

在此上下文中,ab&a 和 &b 分别是 “相同”。在 a&a 产生相同内存地址的意义上相同。尽管如此,使用 a&a 之间存在重要差异,如需深入解释,请阅读以下 difference between “array” and “&array”.

Array a and reduce_storage are allocated in the same way so the are of the same dimension m * n, the value of count argument of MPI_Reduce. I don't understand why I try to run it return this error:

在第二次调用中

MPI_Reduce(&a, &reduce_storage, m * n, MPI_DOUBLE, MPI_SUM, p-1, MPI_COMM_WORLD);

参数 areduce_storage 现在都是 double* 类型,您正在传递 &a&reduce_storage 作为 [=12] 的参数=].这是错误的,因为 &a&reduce_storage 将分别 return 变量 areduce_storage 的地址,这将是指向指针的指针-加倍。

Assuming I use p process, I need to reduce p

旁注:使用 'p' 作为尺寸总数有点混乱,IMO 更好的名称是 total_processesnumber_of_processes 或类似的名称。