MPI_File_set_view 用于使用自定义 MPI_Datatype 作为文件类型的并行文件输出
MPI_File_set_view for parallel file output using custom MPI_Datatype as filetype
我很难理解 MPI_File_set_view 是如何工作的,尤其是第 4 个参数让我很困惑。
int MPI_File_set_view(MPI_File fh, MPI_Offset disp, MPI_Datatype etype, MPI_Datatype filetype, const char *datarep, MPI_Info info)
假设我有 n 个线程,每个线程都有一个名为“v”的长度为 10 的字符数组,该数组的所有条目都等于线程 ID。所以
thread0: v={0,0,0,0,0,0,0,0,0,0}
thread1: v={1,1,1,1,1,1,1,1,1,1}
thread2: v={2,2,2,2,2,2,2,2,2,2}
...
现在我想按以下顺序编写一个包含这些数组值的二进制文件:
file = thread0.v[0], thread1.v[0], thread2.v[0], ..., thread0.v[1], thread1.v[1], thread2.v[1], ..., thread0.v[2], thread1.v[2], thread2.v[2], ...
据我所知,我必须为文件类型参数构造一个 MPI_Datatype,它的大小为 [sizeof(char)*n],其中有一个大小为 [sizeof( char)*threadID] 在 MPI_Char 数据之前,另一个大小为 [sizeof(char)*(n-threadID-1)] 的“洞”在数据之后。我认为这是我犯错误的部分。
我的代码如下所示:
#include<iostream>
#include<mpi.h>
using namespace std;
int main(int argc, char* argv[]){
int myId;
int numProcs;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numProcs);
MPI_Comm_rank(MPI_COMM_WORLD,&myId);
int size=100;
char v[size];
for(int i=0;i<size;i++){
v[i]=myId;
}
int blocklen[numProcs];
MPI_Aint disp[numProcs];
MPI_Datatype type[numProcs];
for(int i=0;i<numProcs;i++){
blocklen[i]=1;
disp[i]=sizeof(char)*myId;
type[i]=MPI_CHAR;
}
MPI_Datatype mytype;
MPI_Type_create_struct(numProcs, blocklen, disp, type, &mytype);
MPI_Type_commit(&mytype);
MPI_File fh;
MPI_File_open(MPI_COMM_WORLD, "binfile", MPI_MODE_WRONLY | MPI_MODE_CREATE, MPI_INFO_NULL, &fh);
MPI_File_set_view(fh, 0, MPI_BYTE, mytype, "native", MPI_INFO_NULL);
MPI_File_write(fh, v, size, MPI_BYTE, MPI_STATUS_IGNORE);
MPI_File_close(&fh);
MPI_Finalize();
return 0;
}
当我对文件“binfile”进行 hexdump 时,我得到了这个(使用 4 个线程):
$ hd binfile
00000000 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
00000010 01 01 01 01 01 01 01 01 01 01 02 03 |............|
0000001c
我哪里出错了?
感谢 Hristo Iliev 的评论,我得以解决我的问题。
函数
int MPI_Type_create_subarray(int ndims, const int array_of_sizes[],
const int array_of_subsizes[], const int array_of_starts[], int order,
MPI_Datatype oldtype, MPI_Datatype *newtype)
成功了。 array_of_sizes 定义新数据类型的大小。 array_of_subsizes 定义部分的大小,它不是 "holes" 的一部分,array_of_starts 定义 "non-hole" 部分的开始位置。
对于任何感兴趣的人,这是工作代码:
#include<iostream>
#include<mpi.h>
using namespace std;
int main(int argc, char* argv[]){
int myId;
int numProcs;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numProcs);
MPI_Comm_rank(MPI_COMM_WORLD,&myId);
int size=100;
char v[size];
for(int i=0;i<size;i++){
v[i]=myId;
}
int array_of_sizes[1];
array_of_sizes[0]=numProcs;
int array_of_subsizes[1];
array_of_subsizes[0]=1;
int array_of_starts[1];
array_of_starts[0]=myId;
MPI_Datatype mytype;
MPI_Type_create_subarray(1,array_of_sizes, array_of_subsizes, array_of_starts, MPI_ORDER_C, MPI_BYTE, &mytype);
MPI_Type_commit(&mytype);
MPI_File fh;
MPI_File_open(MPI_COMM_WORLD, "binfile", MPI_MODE_WRONLY | MPI_MODE_CREATE, MPI_INFO_NULL, &fh);
MPI_File_set_view(fh, 0, MPI_BYTE, mytype, "native", MPI_INFO_NULL);
MPI_File_write(fh, v, size, MPI_BYTE, MPI_STATUS_IGNORE);
MPI_File_close(&fh);
MPI_Finalize();
return 0;
}
我很难理解 MPI_File_set_view 是如何工作的,尤其是第 4 个参数让我很困惑。
int MPI_File_set_view(MPI_File fh, MPI_Offset disp, MPI_Datatype etype, MPI_Datatype filetype, const char *datarep, MPI_Info info)
假设我有 n 个线程,每个线程都有一个名为“v”的长度为 10 的字符数组,该数组的所有条目都等于线程 ID。所以
thread0: v={0,0,0,0,0,0,0,0,0,0}
thread1: v={1,1,1,1,1,1,1,1,1,1}
thread2: v={2,2,2,2,2,2,2,2,2,2}
...
现在我想按以下顺序编写一个包含这些数组值的二进制文件:
file = thread0.v[0], thread1.v[0], thread2.v[0], ..., thread0.v[1], thread1.v[1], thread2.v[1], ..., thread0.v[2], thread1.v[2], thread2.v[2], ...
据我所知,我必须为文件类型参数构造一个 MPI_Datatype,它的大小为 [sizeof(char)*n],其中有一个大小为 [sizeof( char)*threadID] 在 MPI_Char 数据之前,另一个大小为 [sizeof(char)*(n-threadID-1)] 的“洞”在数据之后。我认为这是我犯错误的部分。
我的代码如下所示:
#include<iostream>
#include<mpi.h>
using namespace std;
int main(int argc, char* argv[]){
int myId;
int numProcs;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numProcs);
MPI_Comm_rank(MPI_COMM_WORLD,&myId);
int size=100;
char v[size];
for(int i=0;i<size;i++){
v[i]=myId;
}
int blocklen[numProcs];
MPI_Aint disp[numProcs];
MPI_Datatype type[numProcs];
for(int i=0;i<numProcs;i++){
blocklen[i]=1;
disp[i]=sizeof(char)*myId;
type[i]=MPI_CHAR;
}
MPI_Datatype mytype;
MPI_Type_create_struct(numProcs, blocklen, disp, type, &mytype);
MPI_Type_commit(&mytype);
MPI_File fh;
MPI_File_open(MPI_COMM_WORLD, "binfile", MPI_MODE_WRONLY | MPI_MODE_CREATE, MPI_INFO_NULL, &fh);
MPI_File_set_view(fh, 0, MPI_BYTE, mytype, "native", MPI_INFO_NULL);
MPI_File_write(fh, v, size, MPI_BYTE, MPI_STATUS_IGNORE);
MPI_File_close(&fh);
MPI_Finalize();
return 0;
}
当我对文件“binfile”进行 hexdump 时,我得到了这个(使用 4 个线程):
$ hd binfile
00000000 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
00000010 01 01 01 01 01 01 01 01 01 01 02 03 |............|
0000001c
我哪里出错了?
感谢 Hristo Iliev 的评论,我得以解决我的问题。 函数
int MPI_Type_create_subarray(int ndims, const int array_of_sizes[], const int array_of_subsizes[], const int array_of_starts[], int order, MPI_Datatype oldtype, MPI_Datatype *newtype)
成功了。 array_of_sizes 定义新数据类型的大小。 array_of_subsizes 定义部分的大小,它不是 "holes" 的一部分,array_of_starts 定义 "non-hole" 部分的开始位置。
对于任何感兴趣的人,这是工作代码:
#include<iostream>
#include<mpi.h>
using namespace std;
int main(int argc, char* argv[]){
int myId;
int numProcs;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numProcs);
MPI_Comm_rank(MPI_COMM_WORLD,&myId);
int size=100;
char v[size];
for(int i=0;i<size;i++){
v[i]=myId;
}
int array_of_sizes[1];
array_of_sizes[0]=numProcs;
int array_of_subsizes[1];
array_of_subsizes[0]=1;
int array_of_starts[1];
array_of_starts[0]=myId;
MPI_Datatype mytype;
MPI_Type_create_subarray(1,array_of_sizes, array_of_subsizes, array_of_starts, MPI_ORDER_C, MPI_BYTE, &mytype);
MPI_Type_commit(&mytype);
MPI_File fh;
MPI_File_open(MPI_COMM_WORLD, "binfile", MPI_MODE_WRONLY | MPI_MODE_CREATE, MPI_INFO_NULL, &fh);
MPI_File_set_view(fh, 0, MPI_BYTE, mytype, "native", MPI_INFO_NULL);
MPI_File_write(fh, v, size, MPI_BYTE, MPI_STATUS_IGNORE);
MPI_File_close(&fh);
MPI_Finalize();
return 0;
}