【问题标题】:MPI_Gatherv is not collecting data correctlyMPI_Gatherv 未正确收集数据
【发布时间】:2016-02-17 20:25:23
【问题描述】:

我正在尝试使用MPI_Gatherv 收集不同大小的数组,但由于某种原因,它只收集了第一个处理器中的第一个对象。当我执行上述 for 循环时,我从 xPos 和 yPos 获得正确的值,但是当我将数据收集到 xFinal 和 yFinal 数组并打印出值时,我只得到第一个 x 和 y。所以基本上第一个对象的 (x,y) 为 (0,0) 并且我有 10 个对象,并且所有对象仅在它应该引用的实际对象具有不同 (x, y)

以防万一,counts[rank] 和 displs 肯定是对的,因为我之前用它们来 scatterv。

我是否错误地使用了gatherrv?还是我打印不正确?

for ( a = 0; a < size; a++) {
    if (rank == a) {
        for ( i = 0 ; i < counts[rank]; i++) {
            printf("from procs %d: %lE %lE\n", rank, xPos[i], yPos[i]);
        }
    }
}


MPI_Gatherv(&xPos, counts[rank], MPI_DOUBLE, &xFinal, counts, displs, MPI_DOUBLE,0, MPI_COMM_WORLD);
MPI_Gatherv(&yPos, counts[rank], MPI_DOUBLE, &yFinal, counts, displs, MPI_DOUBLE,0, MPI_COMM_WORLD);


MPI_Finalize();

FILE* f = fopen("universe.out", "wt");
for (i = 0; i < N; i++)
    fprintf(f, "%lE %lE\n", xFinal[i], yFinal[i]);
fclose(f);

【问题讨论】:

    标签: c parallel-processing mpi writetofile


    【解决方案1】:

    您似乎正在同时从所有级别写入文件。您应该将文件写入代码放在if (rank == 0) { ... } 中,只让等级0 写入:

    if (rank == 0)
    {
        FILE* f = fopen("universe.out", "wt");
        for (i = 0; i < N; i++)
            fprintf(f, "%lE %lE\n", xFinal[i], yFinal[i]);
        fclose(f);
    }
    

    否则文件的内容可以是任何内容。

    【讨论】:

    • 哇,这救了我的命!它并没有完全解决我的问题,因为我最终通过引用传递了一些奇怪的参数,这些参数给了我疯狂的数字(我已修复),但这最终让我在文件中看到了一些数字!非常感谢!
    【解决方案2】:

    在我通常的 MPI-IO 倡导者角色中,请考虑 MPI-IO 来解决此类问题。您可以通过让每个进程写入文件来完全跳过收集。此外,如果 N 很大,您不希望进行 N 个文件操作。让 MPI(直接或通过库)让您的生活更轻松。

    首先,基于文本的输出格式真的是您(和您的合作者)想要的吗?如果 Universe.out 变得足够大以至于您想要并行读取它,那么您将面临跨处理器分解文件的挑战。考虑并行 HDF5 (phdf5) 或 parallel-netcdf (pnetcdf) 或任何其他具有自描述可移植文件格式的高级库。

    这是一个示例,说明如何写出所有 x 值,然后写出所有 y 值。

    #include <stdio.h>
    #include <mpi.h>
    #include <unistd.h> //getpid
    #include <stdlib.h> //srandom, random
    
    #define MAX_PARTS 10
    
    int main(int argc, char **argv) {
        int rank, nprocs;
        MPI_Offset nparts; // more than 2 billion particle possible
        int i;
        double *x, *y;
        MPI_Init(&argc, &argv);
        MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
        MPI_Offset start=0, x_end;
        MPI_Info info;
        MPI_File fh;
        MPI_Status status;
        srandom(getpid());
    
        /* demonstrate this works even when particles are not evenly
     * distributed over the processes */
        nparts=((double)random()/RAND_MAX)*MAX_PARTS;
    
        x = malloc(nparts*sizeof(*x));
        y = malloc(nparts*sizeof(*y));
        for (i = 0; i< nparts; i++) {
            /* just some bogus data to see what happens */
            x[i] = rank*100+i;
            y[i] = rank*200+i;
        }
    
        /* not using this now. might tune later if needed */
        MPI_Info_create(&info);
    
        MPI_File_open(MPI_COMM_WORLD, "universe.out",
        MPI_MODE_CREATE|MPI_MODE_WRONLY, info,  &fh);
        MPI_File_set_view(fh, 0, MPI_DOUBLE, MPI_DOUBLE, "native", info);
    
        MPI_Scan(&nparts, &start, 1, MPI_OFFSET, MPI_SUM, MPI_COMM_WORLD);
    
        /* MPI_Scan is a prefix reduction: remove our contribution */
        x_end = start; /* only the last rank will use this in the bcast below */
        start -= nparts;
    
        MPI_Bcast(&x_end, 1, MPI_OFFSET, nprocs-1, MPI_COMM_WORLD);
        MPI_File_write_at_all(fh, start, x, nparts, MPI_DOUBLE, &status);
        MPI_File_write_at_all(fh, start+x_end, y, nparts, MPI_DOUBLE, &status);
    
        MPI_Info_free(&info);
        MPI_File_close(&fh);
    
        MPI_Finalize();
    
    }
    

    可以将 x 数组和 y 数组写成 (x,y) 值对,但是 稍微复杂一点(你必须创建一个 MPI 数据类型)。

    Parallel-NetCDF 有一个“操作组合”优化,可以为 你。 Parallel-HDF5 正在进行“多数据集 i/o”优化 下一个版本。通过这些优化,您可以定义一个 3d 数组,使用 x 和 y 为一维,“粒子标识符”为第三维。然后你 可以发布 x 值的操作,y 值的操作,以及 让图书馆将所有这些整合到一个电话中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-19
      • 2018-04-27
      • 1970-01-01
      • 2018-11-04
      • 1970-01-01
      • 2019-06-02
      • 2020-09-07
      • 2016-10-29
      相关资源
      最近更新 更多