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

C MPI I/O,单进程和多进程输出的混合,c,io,mpi,mpi-io,C,Io,Mpi,Mpi Io,我需要一个MPI C代码来通过MPI I/O将数据写入二进制文件。我需要进程0来写入一个短头,然后我需要整个进程来写入头所指示的自己的数组片段。然后我需要进程0编写另一个头,然后所有进程编写下一个数组的片段,等等。我想出了下面的测试代码,它实际上实现了我想要的。没有人会比我更惊讶 我的问题是,我是MPI I/O的新手,所以我“明白”了吗?我这样做是“正确的方式”还是有更有效或更紧凑的方式 代码是:(顺便说一句,如果您想测试它,请仅用4个过程进行测试。) #包括 #包括 #包括 #包括“mpi.h

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

我的问题是,我是MPI I/O的新手,所以我“明白”了吗?我这样做是“正确的方式”还是有更有效或更紧凑的方式

代码是:(顺便说一句,如果您想测试它,请仅用4个过程进行测试。)

#包括
#包括
#包括
#包括“mpi.h”
#定义第9行
#定义COLS 10
int main(int argc,char*argv[]){
整数大小、秩、行、列;
inti,j,p,ttlcols;
整数大小[]={2*行,2*列};
int subfizes[]={ROWS,COLS};
int开始[]={0,0};
int VAL[行][列];
char hdr[]=“这只是一个标题。\n”;
MPI_状态统计_MPI;
MPI_数据类型子阵列;
MPI_文件fh;
MPI\u偏移量,hdr的结束;
MPI\u信息\u MPI;
MPI_Init(&argc,&argv);
MPI通信大小(MPI通信世界和大小MPI);
MPI_Comm_rank(MPI_Comm_WORLD和rank_MPI);
ttlcols=2*COLS;
/*我们在进程阵列中的位置在哪里*/
col\u mpi=rank\u mpi%2;
行mpi=排名mpi/2;
/*填充数组*/

对于(j=0;j来说,您的方法很好,如果您现在需要一些东西来将位放入文件中,请继续并称自己已完成

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

  • 您可以查阅status对象以了解写入了多少字节,而不是获取位置并转换为字节

  • 如果在写之前有内存来保存所有数据,那么可以使用MPI数据类型来描述I/O(无可否认,创建这种类型可能会很麻烦),然后所有进程都会发出一个集合调用

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

  • 如果进程有不同数量的数据要写入,那么MPI\u EXSCAN是收集谁有哪些数据的好方法。然后,您可以调用MPI\u FILE\u write\u AT\u ALL,以获得文件中正确的偏移量


您是否总是预先知道头的大小,并且它们是否都相同(大小)?如果是这样,您可以为包含头和数据的进程0创建一个视图,为仅包含数据的其他进程创建另一个视图。然后您只需调用一个
MPI\u File\u set\u view()
和两个
MPI\u File\u write()调用
每迭代一次,排名为0,其他排名为一。@Gilles我知道前面的标题大小。不幸的是,它们并不完全相同。我不能改变这一点。不是我的设计。您的代码中有一个错误:
end\u of_hdr
类型为
MPI\u Offset
,您正在使用
MPI\u INT
MPI\u Offset 通常为64位,而
MPI_INT
对应于
INT
,在LP64 Unix系统(*BSD、Linux、Solaris)上仅为32位。在big-endian系统上,将广播非常错误的偏移量。请使用
MPI_偏移量
(如果MPI实现支持)或相应的C类型(检查
MPI.h
)@赫里斯托利耶夫谢谢。我想知道。找不到关于“MPI_偏移”的任何信息在标准中,我尝试了MPI_INT。它起作用了,所以我认为这一定是票证。但我猜不是。我会研究它。再次感谢。奇怪的是,
MPI_AINT
MPI_OFFSET
与第3.2.2节(消息数据)中所有其他预定义的MPI数据类型一起描述至少从2.2版开始。谢谢!Re:你的第三个要点,我只需要一个进程来写标题。我不知道如何做到这一点,不需要隔离那些对MPI_File_write的调用。有没有办法让每个人都调用MPI_File_write,但只有一个进程来写标题?再次感谢!当然。这样做是公平的N个进程调用一个集合操作,但其中只有一个进程有数据。任何进程都可以为“count”参数传入一个0。但是,我建议使用一个集合,其中秩0与数组一起写入头,而其他所有进程都写入数组中自己的部分。明白。再次感谢。您应该使用“MPI_File_write_all”当您写入阵列时-我看到与MPI_文件_写入相比,大型数据集的性能提高了几个数量级。告诉IO库您正在进行集体写入(_all)使it能够在写入之前聚合来自不同进程的数据,例如导致少量大型IO事务,而不是大量小型事务,这可以显著提高性能。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#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;

}