接收缓冲区中的MPI_Gather垃圾(MPI + C)

时间:2018-05-23 20:42:36

标签: c parallel-processing mpi

我是MPI的新手并尝试在多个线程上并行化代码。我需要将大量数据传回主线程,并且无法清理MPI_Gather后得到的内存垃圾。以下是示例代码:

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

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

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

double *total=NULL;
double parcial[15000];
int W=world_size*15000;

if (rank == 0) {
    total=malloc(sizeof(double) * world_size*15000);
}
else if (rank != 0) {
    for(int i=0; i<15000; i++)parcial[i] = rank*i*0.1;
}
MPI_Barrier(MPI_COMM_WORLD);

if(rank==0) for(int ii=0; ii<W; ii++)total[ii]=0.;

MPI_Gather(parcial,15000,MPI_DOUBLE,total,15000,MPI_DOUBLE,0,MPI_COMM_WORLD);

if (rank == 0) {
    int N=world_size*15000;
    for(int i=0; i<N; i++) printf("%f ", total[i]);
}

free(total);
MPI_Finalize();

}

如果你运行带有多个线程的代码(我已经试过3,4,5 ...),它总是在接收缓冲区的开头有垃圾,即使我在调用MPI_Gather之前明确地将total [ii]置为零并设置障碍。是因为我实际上只有两个内核吗?但我已经读过,MPI无论如何都会创建一个虚拟机。有没有办法清理它并获得可靠的聚集?

增加:

我想,这个垃圾可能来自零线程。为什么它不会在第25行之后变为零?

1 个答案:

答案 0 :(得分:3)

摘自MPI_Gather的MPI手册页:

  

每个进程(包括根进程)发送其内容   将缓冲区发送到根进程。

因此,recv缓冲区total的前15000个元素将在根进程中包含parcial的元素。这在您的代码中保留了一致性。

编辑:@Gilles评论说可以使用MPI_IN_PLACE来避免在根进程上进行初始化。这是一个显示其效果的例子:

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


int main(int argc, char *argv[])
{
    int rank, size;

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

    int *in_place_total = calloc(sizeof(int), size);
    int *total = calloc(sizeof(int), size);

    int sendval = rank-5000;

    MPI_Gather(&sendval, 1, MPI_INT,
           total, 1, MPI_INT, 0, MPI_COMM_WORLD);

    if (rank == 0)
        assert(total[0] == -5000);

    if (rank)
        MPI_Gather(&sendval, 1, MPI_INT,
           in_place_total, 1, MPI_INT, 0, MPI_COMM_WORLD);
    else
        MPI_Gather(MPI_IN_PLACE, 1, MPI_INT,
           in_place_total, 1, MPI_INT, 0, MPI_COMM_WORLD);

    if (rank == 0)
        assert(in_place_total[0] == 0);

    free(total);
    free(in_place_total);

    MPI_Finalize();

}