寫的MPI程序需要用到並行IO來操作文件,但是搜遍了度娘都沒有找到多少關於並行IO函數的使用方法。最後在知網搜到了一些有用的論文,看了一下,感覺豁然開朗。
MPI-1對文件的操作是使用綁定語言的函數調用來進行的,通常采用的是串行IO的讀寫方式,一般情況下是用一個主進程打開文件和讀取數據,然後分發給其他進程來處理,這種串行IO數據的通信量很大、效率較低。MPI-2實現了並行IO,允許多個進程同時對文件進行操作,從而避免了文件數據在不同進程間的傳送,對於需要密集文件操作的程序而言,簡直是一大福祉!
並行IO可分為三種方法:指定顯式偏移量、獨立文件指針和共享文件指針,每種方式又可分為阻塞和非阻塞兩種情況。
下面以讀寫一個二進制文件數組為例,闡述這三種方法的函數調用。下面的三個mian函數分別對應三種方法,讀取“data"二進制文件數組(文件內容:行數、列數、數組元素),讀取完整後由進程0輸出其讀取的數據以驗證讀取是否正確,最後所有進程將其讀取的數據寫入一個叫“data2"的二進制文件。怎麼來查看二進制文件的內容以驗證是否讀寫正確呢,或者說二進制文件和可讀內容的文本文件之間怎麼轉換呢?下面也給出簡單代碼。
code:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include"mpi.h" 5 6 #define BLOCK_LOW(rank,size,n) ((rank)*(n)/(size)) 7 #define BLOCK_HIGH(rank,size,n) (BLOCK_LOW((rank)+1,size,n)-1) 8 #define BLOCK_SIZE(rank,size,n) (BLOCK_HIGH(rank,size,n)-BLOCK_LOW(rank,size,n)+1) 9 10 //並行IO:指定顯式偏移的文件操作 11 int main(int argc, char *argv[]) 12 { 13 int size,rank,i; 14 int n,m; 15 float *array; 16 MPI_File fh; 17 MPI_Status status; 18 MPI_Init(&argc,&argv); 19 MPI_Comm_rank(MPI_COMM_WORLD,&rank); 20 MPI_Comm_size(MPI_COMM_WORLD,&size); 21 22 MPI_File_open(MPI_COMM_WORLD,"data",MPI_MODE_RDONLY,MPI_INFO_NULL,&fh); 23 MPI_File_read_at_all(fh,0,&n,1,MPI_INT,&status); //從偏移量0處讀取 24 MPI_File_read_at_all(fh,sizeof(int),&m,1,MPI_INT,&status); //從偏移量1個int處讀取 25 array=(float *)malloc(BLOCK_SIZE(rank,size,n)*m*sizeof(float)); 26 MPI_File_read_at_all(fh,2*sizeof(int)+BLOCK_LOW(rank,size,n)*m*sizeof(float),array,BLOCK_SIZE(rank,size,n)*m,MPI_FLOAT,&status); 27 MPI_File_close(&fh); 28 29 if(rank==0){ 30 printf("rank=%d: %d %d\n",rank,n,m); 31 for(i=0;i<BLOCK_SIZE(rank,size,n)*m;i++){ 32 printf("% .0f",array[i]); 33 if((i+1)%m==0) putchar('\n'); 34 } 35 } 36 37 MPI_File_open(MPI_COMM_WORLD,"data2",MPI_MODE_CREATE|MPI_MODE_WRONLY,MPI_INFO_NULL,&fh); 38 MPI_File_write_at_all(fh,0,&n,1,MPI_INT,&status); 39 MPI_File_write_at_all(fh,sizeof(int),&m,1,MPI_INT,&status); 40 MPI_File_write_at_all(fh,2*sizeof(int)+BLOCK_LOW(rank,size,n)*m*sizeof(float),array,BLOCK_SIZE(rank,size,n)*m,MPI_FLOAT,&status); 41 MPI_File_close(&fh); 42 43 MPI_Finalize(); 44 return 0; 45 } 46 47 /* 48 //並行IO:獨立文件指針 49 int main(int argc,char *argv[]) 50 { 51 int size,rank,i; 52 int n,m; 53 float *array; 54 MPI_File fh; 55 MPI_Status status; 56 MPI_Init(&argc,&argv); 57 MPI_Comm_rank(MPI_COMM_WORLD,&rank); 58 MPI_Comm_size(MPI_COMM_WORLD,&size); 59 60 MPI_File_open(MPI_COMM_WORLD,"data",MPI_MODE_RDONLY,MPI_INFO_NULL,&fh); 61 MPI_File_set_view(fh,0,MPI_INT,MPI_INT,"internal",MPI_INFO_NULL); //設置絕對偏移量為0 62 MPI_File_read_all(fh,&n,1,MPI_INT,&status); //讀取後偏移量自動加1 63 MPI_File_read_all(fh,&m,1,MPI_INT,&status); 64 array=(float *)malloc(BLOCK_SIZE(rank,size,n)*m*sizeof(float)); 65 MPI_File_set_view(fh,2*sizeof(int)+BLOCK_LOW(rank,size,n)*m*sizeof(float),MPI_FLOAT,MPI_FLOAT,"internal",MPI_INFO_NULL);//重置偏移量 66 MPI_File_read_all(fh,array,BLOCK_SIZE(rank,size,n)*m,MPI_INT,&status); 67 MPI_File_close(&fh); 68 69 if(rank==0){ 70 printf("rank=%d: %d %d\n",rank,n,m); 71 for(i=0;i<BLOCK_SIZE(rank,size,n)*m;i++){ 72 printf("% .0f",array[i]); 73 if((i+1)%m==0) putchar('\n'); 74 75 } 76 } 77 78 MPI_File_open(MPI_COMM_WORLD,"data2",MPI_MODE_CREATE|MPI_MODE_WRONLY,MPI_INFO_NULL,&fh); 79 MPI_File_set_view(fh,0,MPI_INT,MPI_INT,"internal",MPI_INFO_NULL); 80 MPI_File_write_all(fh,&n,1,MPI_INT,&status); 81 MPI_File_write_all(fh,&m,1,MPI_INT,&status); 82 MPI_File_set_view(fh,2*sizeof(int)+BLOCK_LOW(rank,size,n)*m*sizeof(float),MPI_FLOAT,MPI_FLOAT,"internal",MPI_INFO_NULL); 83 MPI_File_write_all(fh,array,BLOCK_SIZE(rank,size,n)*m,MPI_FLOAT,&status); 84 MPI_File_close(&fh); 85 86 MPI_Finalize(); 87 } 88 */ 89 90 /* 91 //並行IO:共享文件指針 92 int main(int argc,char *argv[]) 93 { 94 int size,rank,i; 95 int n,m; 96 float *array; 97 MPI_File fh; 98 MPI_Status status; 99 MPI_Init(&argc,&argv); 100 MPI_Comm_rank(MPI_COMM_WORLD,&rank); 101 MPI_Comm_size(MPI_COMM_WORLD,&size); 102 103 MPI_File_open(MPI_COMM_WORLD,"data",MPI_MODE_RDONLY,MPI_INFO_NULL,&fh); 104 MPI_File_read_at_all(fh,0,&n,1,MPI_INT,&status); //指定顯式偏移的讀取 105 MPI_File_read_at_all(fh,sizeof(int),&m,1,MPI_INT,&status); 106 array=(float *)malloc(BLOCK_SIZE(rank,size,n)*m*sizeof(float)); 107 MPI_File_seek_shared(fh,2*sizeof(int),MPI_SEEK_SET); //共享文件指針,偏移量是2個int 108 MPI_File_read_ordered(fh,array,BLOCK_SIZE(rank,size,n)*m,MPI_FLOAT,&status); //按序讀取 109 MPI_File_close(&fh); 110 111 if(rank==0){ 112 printf("rank=%d: %d %d\n",rank,n,m); 113 for(i=0;i<BLOCK_SIZE(rank,size,n)*m;i++){ 114 printf("% .0f",array[i]); 115 if((i+1)%m==0) putchar('\n'); 116 117 } 118 } 119 120 MPI_File_open(MPI_COMM_WORLD,"data2",MPI_MODE_CREATE|MPI_MODE_WRONLY,MPI_INFO_NULL,&fh); 121 MPI_File_write_at_all(fh,0,&n,1,MPI_INT,&status); //指定顯式偏移的寫入 122 MPI_File_write_at_all(fh,sizeof(int),&m,1,MPI_INT,&status); 123 MPI_File_seek_shared(fh,2*sizeof(int),MPI_SEEK_SET); //共享文件指針,偏移量是2個int 124 MPI_File_write_ordered(fh,array,BLOCK_SIZE(rank,size,n)*m,MPI_FLOAT,&status); //按序寫入 125 MPI_File_close(&fh); 126 127 MPI_Finalize(); 128 } 129 */
1 //將二進制數組文件轉換為文本文件。要求二進制文件的內容:行數 列數 數組元素 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 typedef float type; 6 7 int main() 8 { 9 int i,j; 10 int n,m; 11 type **array; 12 FILE *fp; 13 fp=fopen("data","rb"); 14 fread(&n,sizeof(int),1,fp); 15 fread(&m,sizeof(int),1,fp); 16 17 array=(type **)malloc(n*sizeof(type *)); 18 *array=(type *)malloc(n*m*sizeof(type)); 19 for(i=1;i<n;i++) array[i]=array[i-1]+m; 20 21 fread(&array[0][0],n*m*sizeof(type),1,fp); //注意不能是地址 array 22 fclose(fp); 23 24 fp=fopen("data.txt","w"); 25 fprintf(fp," %d %d\n",n,m); 26 for(i=0;i<n;i++){ 27 for(j=0;j<m;j++) 28 fprintf(fp,"% f ",array[i][j]); 29 putc('\n',fp); 30 } 31 fprintf(stdout,"Successfully!\n"); 32 }
1 //將數組文本文件轉換為二進制文件。要求文本文件的內容:行數 列數 數組元素 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 typedef float type; 6 7 int main() 8 { 9 int i,j; 10 int n,m; 11 type **array; 12 FILE *fp; 13 fp=fopen("data.txt","r"); 14 fscanf(fp,"%d",&n); 15 fscanf(fp,"%d",&m); 16 17 array=(type **)malloc(n*sizeof(type *)); 18 *array=(type *)malloc(n*m*sizeof(type)); 19 for(i=1;i<n;i++) array[i]=array[i-1]+m; 20 21 for(i=0;i<n;i++) 22 for(j=0;j<m;j++) 23 fscanf(fp,"%f",&array[i][j]); 24 fclose(fp); 25 26 fp=fopen("data","wb"); 27 fwrite(&n,sizeof(int),1,fp); 28 fwrite(&m,sizeof(int),1,fp); 29 fwrite(&array[0][0],n*m*sizeof(type),1,fp); //注意不能是地址 &array 30 fclose(fp); 31 fprintf(stdout,"Successfully!\n"); 32 }
一個示例的文本文件數組data.txt:
8 8
1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
2.000000 2.000000 2.000000 2.000000 2.000000 2.000000 2.000000 2.000000
3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000
4.000000 4.000000 4.000000 4.000000 4.000000 4.000000 4.000000 4.000000
5.000000 5.000000 5.000000 5.000000 5.000000 5.000000 5.000000 5.000000
6.000000 6.000000 6.000000 6.000000 6.000000 6.000000 6.000000 6.000000
7.000000 7.000000 7.000000 7.000000 7.000000 7.000000 7.000000 7.000000
8.000000 8.000000 8.000000 8.000000 8.000000 8.000000 8.000000 8.000000