MPI 非标准类型的分布式读取

Posted

技术标签:

【中文标题】MPI 非标准类型的分布式读取【英文标题】:MPI Distributed reading over a non-standard type 【发布时间】:2016-03-01 21:22:03 【问题描述】:

我正在尝试读取包含 char 和 double 序列的二进制文件。 (例如 0 0.125 1 1.4 0 2.3 1 4.5,但写入二进制文件)。我创建了一个简单的结构输入,以及一个 MPI 数据类型,我将调用与此结构对应的 mpi_input。

typedef struct  char type; double value  input;

我想使用MPI_File_read_at_all 并行读取我的文件(即这里使用不同的处理器)。我想在这个函数中使用数据类型 mpi_input。

问题是,我认为这个函数需要一个缓冲区,它会一直写入到最后。我尝试使用input *buffer,但这会由于数据结构对齐而产生问题。您对如何做到这一点有任何想法吗?

这是一个最小的工作示例:

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

int main(int argc, char** argv)

    typedef struct
    
        double val;
        char type;
     input;

    int rank, size;

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

    assert(size == 4);

    MPI_File in;
    MPI_Offset filesize;
    MPI_File_open(MPI_COMM_WORLD, argv[1], MPI_MODE_RDONLY, MPI_INFO_NULL, &in);
    MPI_File_get_size(in, &filesize);

    int mysize = filesize/size;
    int globalstart = rank * mysize;

    input *chunk = malloc(sizeof(input)*2);

    int n = 128;
    int m = 256;

    int blocks[2] = 1,1;
    MPI_Datatype types[2] = MPI_BYTE, MPI_DOUBLE;
    MPI_Aint displacements[2];
    MPI_Datatype cell_type;
    MPI_Aint charex, doublex;
    displacements[0] = offsetof(input, type);
    displacements[1] = offsetof(input, val);
    MPI_Type_create_struct(2, blocks, displacements, types, &cell_type);
    MPI_Type_commit(&cell_type);

    MPI_File_read_at_all(in, globalstart, chunk, mysize, cell_type, MPI_STATUS_IGNORE);
    if(rank == 0)
        printf("0 - Got %d %f\n", chunk->val, chunk->type);
    if(rank == 4)
        printf("Got %d %f\n", chunk->val, chunk->type);

    MPI_File_close(&in);
    MPI_Finalize();

下面是生成简单二进制文件的代码:

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

int main()

    FILE *fp;
    char* filename = "test.dump";
    fp = fopen(filename, "wb");

    char bla = 8;
    for(double i = 0; i < 8; i++)
    
        fwrite(&bla, sizeof(char), 1, fp);
        bla--;
        fwrite(&i, sizeof(double), 1, fp);
    

    fclose(fp);

【问题讨论】:

【参考方案1】:

您提供的MPI_File_read_at_all 参数错误。在 MPI 中,与要发送/接收/读取/写入的数据相关的参数几乎总是以以下形式的三元组形式给出:buffer, #elements, datatype

在您的情况下,#elements 等于 mysize,它以字节为单位,而不是数据类型 cell_type 的元素数量。结果,函数读取的元素超出了缓冲区的容量,从而破坏了堆。

您应该做的是将mysize 除以数据类型的大小(这不是 sizeof(input)!):

int cell_type_size;
MPI_Type_size(cell_type, &cell_type_size);

...

MPI_File_read_at_all(in, globalstart,
    chunk, mysize / cell_type_size, cell_type, MPI_STATUS_IGNORE);
//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//         data specification triplet

此外,您的第二个 printf 语句将永远不会执行,因为在 4 个 MPI 进程的情况下,rank 会从 0 变为 3

【讨论】:

以上是关于MPI 非标准类型的分布式读取的主要内容,如果未能解决你的问题,请参考以下文章

MPI_SEND 在 MPI_BARRIER 之后停止工作

从所有MPI流程的标准输入读取

用 MPI IO 写几个分布式数组

结构填充和非阻塞通信缓冲区问题导致的 MPI 派生数据类型问题

将 MPI_Scatter 与 MPI_Type_vector 一起使用时列的意外分布

如何用matlab进行参数以及非参数概率密度估计