我正在研究C MPI代码。它有一个结构:
typedef struct mystruct_s{
double interesting_data;
int boring_data;
int trivial_data;
}mystruct;
现在,每个进程都有这些结构的数组,比如说
mystruct my_own_struct[M][N];
其中M和N是“大”,并且所有各种进程数组组成一个大的mystruct
数组。
现在,我需要将interesting_data
值输出到文件中的单个数组中。正如我试图用变量名称来表示,我不想输出结构的其他部分。我想使用MPI I / O来做到这一点。当然,我可以在每个进程中建立一个双数组并将interesting_data
复制到其中并从那里获取它。但是,这会大大增加内存使用量,而且编码也不是非常优雅。我还在学习MPI I / O和MPI派生数据类型。有没有办法使用它们立即从结构数组中“提取”interesting_data
并将其输出到具有MPI I / O的大型数组?
答案 0 :(得分:4)
如果感兴趣的数据是单个double
字段,那么您只需创建一个MPI_DOUBLE
的调整大小版本,其范围与结构相同:
MPI_Datatype newtype;
MPI_Type_create_resized(MPI_DOUBLE, 0L, sizeof(mystruct), &newtype);
MPI_Type_commit(&newtype);
现在,当提供该数据类型时,MPI将获取一个double
值,然后跳过结构的其余部分,从而降落到下一个double
值。等等。
您现在可以使用例如:
存储数据MPI_File fh;
MPI_File_open(MPI_COMM_WORLD, "interesting_data.dat",
MPI_MODE_CREATE | MPI_MODE_WRONLY,
MPI_INFO_NULL, &fh);
MPI_File_set_view(fh, rank * M*N * sizeof(double), // possible integer overflow!!!
MPI_DOUBLE, MPI_DOUBLE, "native", MPI_INFO_NULL);
MPI_File_write(fh, &my_own_struct[0][0].interesting_data, M*N, newtype,
MPI_STATUS_IGNORE);
MPI_File_close(&fh);
MPI_File_set_view
定位每个排名的文件指针,并告诉MPI不执行任何二进制转换。然后,MPI_File_write
调用将合并interesting_data
字段,并将它们作为单个块写入文件视图指定的位置。即使interesting_data
不是结构的第一个字段,它也会起作用。
如果interesting_data
包含多个结构字段,例如
typedef structure _foo
{
int couldnt_care_less;
double interesting_bar;
int not_interesting;
int interesting_baz;
double less_interesting;
} foo;
首先应创建结构类型:
MPI_Datatype stype;
int lens[2] = { 1, 1 };
MPI_Aint disps[2] = { offsetof(foo, interesting_bar), offsetof(foo, interesting_baz) };
MPI_Datatype types[2] = { MPI_DOUBLE, MPI_INT };
MPI_Type_create_struct(2, lens, disps, types, &stype);
// MPI_Type_commit(&stype) is not necessary
现在必须调整类型的大小,与上面的简单示例完全相同:
MPI_Datatype newtype;
MPI_Aint lb, extent;
MPI_Type_get_extent(stype, &lb, &extent);
MPI_Type_create_resized(stype, lb, sizeof(foo), &newtype);
MPI_Type_commit(&newtype);
此过程使新数据类型具有与stype
相同的下限,这将简化写入调用。诀窍是正确设置文件视图。它需要创建另一种结构类型,包括它们之间没有间隔的有趣字段(除非你想通过在文件中包含垃圾来浪费磁盘空间):
MPI_Datatype ftype;
int lens[2] = { 1, 1 };
MPI_Aint disps[2] = { 0, sizeof(double) };
MPI_Datatype types[2] = { MPI_DOUBLE, MPI_INT };
MPI_Type_create_struct(2, lens, disps, types, &ftype);
MPI_Type_commit(&ftype);
然后使用此数据类型设置文件视图:
// possible integer overflow!!!
MPI_Offset offset = rank * M*N * (sizeof(double) + sizeof(int));
MPI_File_set_view(fh, offset, ftype, ftype, "native", MPI_INFO_NULL);
MPI_File_write(fh, my_own_struct, M*N, newtype, MPI_STATUS_IGNORE);
这是有效的,因为ftype
和newtype
是一致的 - 它们由相同的基本元素(一个double
和一个int
)组成,并且顺序相同。< / p>