MPI I / O,单进程和多进程输出的混合

我需要一个MPI C代码通过MPI I / O将数据写入二进制文件。 我需要进程0来编写一个短标题,然后我需要整个进程范围来编写标题所指示的自己的数组。 然后我需要进程0来编写另一个头,然后是所有进程编写下一个数组的部分,等等。我想出了以下测试代码,它实际上做了我想要的。 没有人比我更惊讶。

我的问题是,我是MPI I / O的新手。 所以我“得到它”? 我这样做是“正确的方式”还是有更高效或更紧凑的方式来做到这一点?

代码是:(顺便说一句,如果您考虑测试此function,请仅使用4个触发器进行测试。)

#include  #include  #include  #include "mpi.h" #define ROWS 9 #define COLS 10 int main(int argc, char *argv[]) { int size_mpi, rank_mpi, row_mpi, col_mpi; int i,j,p,ttlcols; int sizes[]= {2*ROWS,2*COLS}; int subsizes[]= {ROWS,COLS}; int starts[] = {0,0}; int vals[ROWS][COLS]; char hdr[] = "This is just a header.\n"; MPI_Status stat_mpi; MPI_Datatype subarray; MPI_File fh; MPI_Offset offset, end_of_hdr; MPI_Info info_mpi; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD,&size_mpi); MPI_Comm_rank(MPI_COMM_WORLD,&rank_mpi); ttlcols = 2*COLS; /* Where are we in the array of processes? */ col_mpi = rank_mpi%2; row_mpi = rank_mpi/2; /* Populate the array */ for (j=0; j<ROWS; j++){ for (i=0; i<COLS; i++){ vals[j][i] = ttlcols*(ROWS*row_mpi + j) + COLS*col_mpi + i; } } /* MPI derived datatype for setting a file view */ starts[0] = row_mpi*ROWS; starts[1] = col_mpi*COLS; MPI_Type_create_subarray(2, sizes, subsizes, starts, MPI_ORDER_C, MPI_INT, &subarray); MPI_Type_commit(&subarray); /* open the file */ printf("opening file\n"); MPI_File_open(MPI_COMM_WORLD, "arrdata.dat", MPI_MODE_WRONLY | MPI_MODE_CREATE, MPI_INFO_NULL, &fh); printf("opened file\n"); /* set the initial file view */ MPI_File_set_view(fh, 0, MPI_CHAR, MPI_CHAR, "native", MPI_INFO_NULL); /* proc 0 writes first header */ if (rank_mpi == 0) { MPI_File_write(fh, (void*)hdr, strlen(hdr), MPI_CHAR, &stat_mpi); MPI_File_get_position(fh, &offset); MPI_File_get_byte_offset(fh, offset, &end_of_hdr); } /* everybody has to know where proc 0 stopped writing */ MPI_Bcast((void*)&end_of_hdr, 1, MPI_INT, 0, MPI_COMM_WORLD); /* re-set file view for writing first array */ MPI_File_set_view(fh, end_of_hdr, MPI_INT, subarray, "native", MPI_INFO_NULL); /* and write the array */ MPI_File_write(fh, (void*)vals, ROWS*COLS, MPI_INT, &stat_mpi); /* now go through the whole thing again to test */ MPI_File_get_position(fh, &offset); MPI_File_get_byte_offset(fh, offset, &end_of_hdr); MPI_File_set_view(fh, end_of_hdr, MPI_CHAR, MPI_CHAR, "native", MPI_INFO_NULL); if (rank_mpi == 0) { MPI_File_write(fh, (void*)hdr, strlen(hdr), MPI_CHAR, &stat_mpi); MPI_File_get_position(fh, &offset); MPI_File_get_byte_offset(fh, offset, &end_of_hdr); } MPI_Bcast((void*)&end_of_hdr, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_File_set_view(fh, end_of_hdr, MPI_INT, subarray, "native", MPI_INFO_NULL); MPI_File_write(fh, (void*)vals, ROWS*COLS, MPI_INT, &stat_mpi); MPI_File_close(&fh); MPI_Finalize(); return 0; } 

你的方法很好,如果你现在需要一些东西把比特放在一个文件中,那就去做吧。

以下是一些提高效率的建议:

  • 您可以查询状态对象,了解写入的字节数,而不是获取位置并转换为字节。

  • 如果在写入之前有内存来保存所有数据,则可以使用MPI数据类型描述您的I / O(诚然,最终可能会创建一个痛苦的I / O)。 然后所有进程都会发出一个集体调用。

  • 您应该使用集体I / O而不是独立的I / O. “质量库”应该能够为您提供相同甚至更好的性能(如果没有,您可以提出MPI实现的问题)。

  • 如果进程具有不同的数据量,MPI_EXSCAN是收集谁拥有哪些数据的好方法。 然后,您可以将MPI_FILE_WRITE_AT_ALL调用到文件中的正确偏移量。