c - MPI_收集接收缓冲区中的垃圾 (MPI+C)

标签 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 行之后它不归零?

最佳答案

摘自 MPI_Gather 的 MPI 手册页:

Each process (root process included) sends the contents of its send buffer to the root process.

因此,recv 缓冲区的前 15000 个元素 total 将包含根进程上的 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();

}

关于c - MPI_收集接收缓冲区中的垃圾 (MPI+C),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50497163/

相关文章:

c - Unix系统编程: get a network identifier to be passed to getaddrinfo

c - openmp程序中出现奇怪的错误

c# - 跟踪并行 Foreach 线程

mpi - 事件驱动的 MPI

c - @zero_extendqisi2 的含义

iphone - sscanf 在 iPhone OS 3.1.2 上是线程安全的吗?

c - mpirun : "alarm clock" 意外返回消息

C/Fortran 混合代码以一种奇怪的方式使用 MPI/ScaLAPACK 段错误

c - 控制台输出中的粗体文本

matlab - 并行与非并行matlab的脚本——parfor的使用