Io 创建动态大小的MPI文件视图

Io 创建动态大小的MPI文件视图,io,mpi,Io,Mpi,我想使用集合MPI I/O编写一个二进制文件 struct soln_dynamic_t { int int_data[2]; double *u; /* Length constant for all instances of this struct */ }; 然后,每个处理器基于派生类型创建一个视图,并写入该视图 我把*u替换为u[10](参见下面的完整代码),但最终,我想为u创建一个动态长度数组。(如果有关系,那么对于任何运行,soln\u dynamic\t的所有

我想使用集合MPI I/O编写一个二进制文件

struct soln_dynamic_t
{
    int int_data[2];
    double *u;   /* Length constant for all instances of this struct */
};
然后,每个处理器基于派生类型创建一个视图,并写入该视图

我把
*u
替换为
u[10]
(参见下面的完整代码),但最终,我想为
u
创建一个动态长度数组。(如果有关系,那么对于任何运行,
soln\u dynamic\t
的所有实例的长度都是固定的,但在编译时是未知的。)

处理这个问题的最佳方法是什么

我读过几篇关于为什么我不能使用
soln\u dynamic\t
直接作为MPI结构。问题是处理器不能保证在
u[0]
int\u数据[0]
之间有相同的偏移量。(是这样吗?)

另一方面,结构

struct soln_static_t
{
    int int_data[2];
    double u[10];     /* fixed at compile time */
};
之所以有效,是因为各处理器之间的偏移量保证相同

我考虑了几种方法:

  • 基于手动定义的偏移等创建视图,而不是使用派生类型

  • 将MPI结构基于另一种MPI类型,即“`*u`”的连续类型(这是允许的吗?)

我猜一定有一个标准的方法来做到这一点。任何建议都会很有帮助

关于这个问题的其他几篇文章也很有帮助,尽管它们主要涉及通信而不是文件I/O

以下是完整的代码::

#include <mpi.h>

typedef struct 
{
    int int_data[2];
    double u[10];  /* Make this a dynamic length (but fixed) */
} soln_static_t;


void build_soln_type(int n, int* int_data, double *u, MPI_Datatype *soln_t)
{
    int block_lengths[2] = {2,n};
    MPI_Datatype typelist[2] = {MPI_INT, MPI_DOUBLE};

    MPI_Aint disp[2], start_address, address;    
    MPI_Address(int_data,&start_address);
    MPI_Address(u,&address);
    disp[0] = 0;
    disp[1] = address-start_address;

    MPI_Datatype tmp_type;
    MPI_Type_create_struct(2,block_lengths,disp,typelist,&tmp_type);

    MPI_Aint extent;
    extent = block_lengths[0]*sizeof(int) + block_lengths[1]*sizeof(double);
    MPI_Type_create_resized(tmp_type, 0, extent, soln_t);
    MPI_Type_commit(soln_t);
}

void main(int argc, char** argv)
{
    MPI_File   file;
    int globalsize, localsize, starts, order;

    MPI_Datatype localarray, soln_t;
    int rank, nprocs, nsize = 10;  /* must match size in struct above */

    /* --- Initialize MPI */
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);

    /* --- Set up data to write out */
    soln_static_t data;
    data.int_data[0] = nsize;
    data.int_data[1] = rank;
    data.u[0] = 3.14159;  /* To check that data is written as expected */
    build_soln_type(nsize, data.int_data, data.u, &soln_t);

    MPI_File_open(MPI_COMM_WORLD, "bin.out", 
                  MPI_MODE_CREATE|MPI_MODE_WRONLY,
                  MPI_INFO_NULL, &file);

    /* --- Create file view for this processor */
    globalsize = nprocs;  
    localsize = 1;
    starts = rank;
    order = MPI_ORDER_C;

    MPI_Type_create_subarray(1, &globalsize, &localsize, &starts, order, 
                             soln_t, &localarray);
    MPI_Type_commit(&localarray);

    MPI_File_set_view(file, 0, soln_t, localarray, 
                           "native", MPI_INFO_NULL);

    /* --- Write data into view */
    MPI_File_write_all(file, data.int_data, 1, soln_t, MPI_STATUS_IGNORE);

    /* --- Clean up */
    MPI_File_close(&file);

    MPI_Type_free(&localarray);
    MPI_Type_free(&soln_t);

    MPI_Finalize();
}
#包括
类型定义结构
{
int_数据[2];
双u[10];/*使其成为动态长度(但固定)*/
}soln_static_t;
void build\u soln\u类型(int n,int*int\u数据,double*u,MPI\u数据类型*soln\u t)
{
int block_length[2]={2,n};
MPI_数据类型类型列表[2]={MPI_INT,MPI_DOUBLE};
MPI维护disp[2],开始地址,地址;
MPI_地址(int_数据和start_地址);
MPI_地址(u和地址);
disp[0]=0;
disp[1]=地址-起始地址;
MPI_数据类型tmp_类型;
MPI类型创建结构(2、块长度、显示、类型列表和tmp类型);
MPI保持范围;
区段=块长度[0]*sizeof(int)+块长度[1]*sizeof(double);
MPI类型创建大小调整(tmp类型,0,范围,解决方案);
MPI类型提交(解决方案);
}
void main(整型argc,字符**argv)
{
MPI_文件;
int globalsize、localsize、start、order;
MPI_数据类型localarray,soln_t;
int-rank,nprocs,nsize=10;/*必须与上面结构中的大小匹配*/
/*---初始化MPI*/
MPI_Init(&argc,&argv);
MPI通信等级(MPI通信世界和等级);
MPI通信大小(MPI通信世界和NPROC);
/*---设置要写出的数据*/
soln_静态数据;
data.int_data[0]=nsize;
data.int_data[1]=秩;
data.u[0]=3.14159;/*检查数据是否按预期写入*/
构建解决方案类型(nsize、data.int\u data、data.u和soln\u t);
MPI文件打开(MPI通信世界,“bin.out”,
MPI_模式|仅创建| MPI_模式|,
MPI\u信息\u NULL和文件);
/*---为此处理器创建文件视图*/
globalsize=nprocs;
localsize=1;
开始=排名;
订单=MPI\u订单\u C;
MPI\u类型\u创建\u子阵列(1、&globalsize、&localsize、&starts、order、,
解决方案和本地阵列);
MPI_类型_提交(&localarray);
MPI\u文件\u集合\u视图(文件,0,解决方案,本地数组,
“本机”,MPI\u信息为空);
/*---将数据写入视图*/
MPI文件写入全部(文件,data.int数据,1,解决方案,MPI状态忽略);
/*---清理*/
MPI\u文件\u关闭(&文件);
MPI_类型_free(&localarray);
无MPI类型(和解决方案);
MPI_Finalize();
}

由于
soln\u dynamic\u t
类型的
u
数组的大小在运行时是已知的,并且在运行后不会改变,因此我建议使用另一种方法

基本上,您将所有连续数据存储在内存中:

typedef struct
{
    int int_data[2];
    double u[];  /* Make this a dynamic length (but fixed) */
} soln_dynamic_t;
然后您必须手动分配此结构

soln_dynamic_t * alloc_soln(int nsize, int count) {
    return (soln_dynamic_t *)calloc(offsetof(soln_dynamic_t, u)+nsize*sizeof(double), count);
}
注意:您不能直接访问
soln\u dynamic\u t
数组,因为编译时大小未知。相反,您必须手动计算指针

soln_dynamic_t *p = alloc_soln(10, 2);
p[0].int_data[0] = 1;  // OK
p[0].u[0] = 2;         // OK
p[1].int_data[0] = 3;  // KO ! since sizeof(soln_dynamic_t) is unknown at compile time.
这是您的程序的完整重写版本

#include <mpi.h>
#include <malloc.h>

typedef struct 
{
    int int_data[2];
    double u[];  /* Make this a dynamic length (but fixed) */
} soln_dynamic_t;


void build_soln_type(int n, MPI_Datatype *soln_t)
{
    int block_lengths[2] = {2,n};
    MPI_Datatype typelist[2] = {MPI_INT, MPI_DOUBLE};
    MPI_Aint disp[2];

    disp[0] = offsetof(soln_dynamic_t, int_data);
    disp[1] = offsetof(soln_dynamic_t, u);

    MPI_Datatype tmp_type;
    MPI_Type_create_struct(2,block_lengths,disp,typelist,&tmp_type);

    MPI_Aint extent;
    extent = offsetof(soln_dynamic_t, u) + block_lengths[1]*sizeof(double);
    MPI_Type_create_resized(tmp_type, 0, extent, soln_t);
    MPI_Type_free(&tmp_type);
    MPI_Type_commit(soln_t);
}

soln_dynamic_t * alloc_soln(int nsize, int count) {
    return (soln_dynamic_t *)calloc(offsetof(soln_dynamic_t, u) + nsize*sizeof(double), count);
}

int main(int argc, char** argv)
{
    MPI_File   file;
    int globalsize, localsize, starts, order;

    MPI_Datatype localarray, soln_t;
    int rank, nprocs, nsize = 10;  /* must match size in struct above */

    /* --- Initialize MPI */
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);

    /* --- Set up data to write out */
    soln_dynamic_t *data = alloc_soln(nsize,1);
    data->int_data[0] = nsize;
    data->int_data[1] = rank;
    data->u[0] = 3.14159;  /* To check that data is written as expected */
    build_soln_type(nsize, &soln_t);

    MPI_File_open(MPI_COMM_WORLD, "bin2.out", 
                  MPI_MODE_CREATE|MPI_MODE_WRONLY,
                  MPI_INFO_NULL, &file);

    /* --- Create file view for this processor */
    globalsize = nprocs;  
    localsize = 1;
    starts = rank;
    order = MPI_ORDER_C;

    MPI_Type_create_subarray(1, &globalsize, &localsize, &starts, order, 
                             soln_t, &localarray);
    MPI_Type_commit(&localarray);

    MPI_File_set_view(file, 0, soln_t, localarray, 
                           "native", MPI_INFO_NULL);

    /* --- Write data into view */
    MPI_File_write_all(file, data, 1, soln_t, MPI_STATUS_IGNORE);

    /* --- Clean up */
    MPI_File_close(&file);

    MPI_Type_free(&localarray);
    MPI_Type_free(&soln_t);

    MPI_Finalize();
    return 0;
}
#包括
#包括
类型定义结构
{
int_数据[2];
双u[];/*使其成为动态长度(但固定)*/
}soln_dynamic_t;
无效生成解决类型(int n,MPI\u数据类型*soln\u t)
{
int block_length[2]={2,n};
MPI_数据类型类型列表[2]={MPI_INT,MPI_DOUBLE};
MPI_Aint disp[2];
disp[0]=偏移量(解决方案动态数据、内部数据);
disp[1]=偏移量(soln\u dynamic\u t,u);
MPI_数据类型tmp_类型;
MPI类型创建结构(2、块长度、显示、类型列表和tmp类型);
MPI保持范围;
范围=偏移量(soln_dynamic_t,u)+块长度[1]*sizeof(double);
MPI类型创建大小调整(tmp类型,0,范围,解决方案);
无MPI类型(&tmp类型);
MPI类型提交(解决方案);
}
解决方案动态解决方案分配解决方案(整数大小,整数计数){
return(soln_dynamic_t*)calloc(offsetof(soln_dynamic_t,u)+nsize*sizeof(double),count);
}
int main(int argc,字符**argv)
{
MPI_文件;
int globalsize、localsize、start、order;
MPI_数据类型localarray,soln_t;
int-rank,nprocs,nsize=10;/*必须与上面结构中的大小匹配*/
/*---初始化MPI*/
MPI_Init(&argc,&argv);
MPI通信等级(MPI通信世界和等级);
MPI通信大小(MPI通信世界和NPROC);
/*---设置要写出的数据*/
soln_dynamic_t*data=alloc_soln(nsize,1);
数据->内部数据[0]=nsize;
数据->内部数据[1]=排名;
data->u[0]=3.14159;/*检查数据是否按预期写入*/
构建解决方案类型(nsize和soln\t);
MPI文件打开(MPI通信世界,“bin2.out”,
MPI_模式|仅创建| MPI_模式|,
MPI\u信息\u NULL和文件);
/*---为此处理器创建文件视图*/
globalsize=nprocs;
localsize=1;