C 在简单MPI代码中读取和写入测试文件时出错

C 在简单MPI代码中读取和写入测试文件时出错,c,mpi,C,Mpi,我有一个MPI代码,进程读取一个二进制文件,然后再写回来。数据的分布方式是进程0读取(然后写入)文件的前半部分,而进程1读取(然后写入)文件的后半部分。现在的问题是输入和输出文件不匹配(diff显示它们不同)。如果只有一个流程,则一切正常。有人能指出哪里出了问题吗 使用OpenMPI,编译为:mpicc-Wall test\u mpi.c-o test\u mpi 运行方式:mpirun-np2./test\u mpi 提前谢谢 #include <stdio.h> #include

我有一个MPI代码,进程读取一个二进制文件,然后再写回来。数据的分布方式是进程0读取(然后写入)文件的前半部分,而进程1读取(然后写入)文件的后半部分。现在的问题是输入和输出文件不匹配(diff显示它们不同)。如果只有一个流程,则一切正常。有人能指出哪里出了问题吗

使用OpenMPI,编译为:mpicc-Wall test\u mpi.c-o test\u mpi
运行方式:mpirun-np2./test\u mpi

提前谢谢

#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>

int main(int argc, char** argv) {

    int rank, np, i;  //np = no. of processes
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &np);

    int filesize = 48*1048576;  //input filesize 48MB

    double *data = (double*) malloc (filesize/np);
    FILE* fpa;
    fpa = fopen ( "512_featurevec.out", "rb");
    fseek(fpa, filesize/np*rank, SEEK_SET);
    printf("read: %d\n", (int)fread(&data[0], sizeof(double), filesize/(np*sizeof(double)), fpa));
    fclose(fpa);

    char* outfile = "outfile.txt";
    for(i=0; i<np; i++) {
        if(rank == i) {
            fpa = fopen ( outfile, "ab");
            fseek(fpa, filesize/np*rank, SEEK_SET);
            fwrite ( &data[0], sizeof(double), filesize/(np*sizeof(double)), fpa);
            fclose ( fpa );
        }   
    }   

    free(data);
    MPI_Finalize();
    exit(0);
}
#包括
#包括
#包括
int main(int argc,字符**argv){
int rank,np,i;//np=进程数
MPI_Init(&argc,&argv);
MPI通信等级(MPI通信世界和等级);
MPI通信大小(MPI通信世界和np);
int filesize=48*1048576;//输入文件大小48MB
double*数据=(double*)malloc(filesize/np);
档案*fpa;
fpa=fopen(“512_特征向量输出”、“rb”);
fseek(fpa,文件大小/np*rank,SEEK\u SET);
printf(“读取:%d\n”,(int)fread(&data[0],sizeof(double),filesize/(np*sizeof(double)),fpa));
fclose(fpa);
char*outfile=“outfile.txt”;

对于(i=0;i而言,问题似乎是由于每个孩子都在打开文件进行写入,这导致了争用


尝试让文件名取决于等级(例如,写入
out file.txt.(等级)
,查看是否所有输出都匹配。

回答我自己的问题,但这是可行的:

char* outfile = "outfile.txt";
    for(i=0; i<np; i++) {
        if(rank == i) {
            fpa = fopen ( outfile, "ab");
            fseek(fpa, filesize/np*rank, SEEK_SET);
            fwrite ( &data[0], sizeof(double), filesize/(np*sizeof(double)), fpa);
            fclose ( fpa );
        } 
        MPI_Barrier(comm);  
    } 
char*outfile=“outfile.txt”;

对于(i=0;i如果您已经在使用MPI,并且很难使用seek来分割文件,而不是使用POSIX,那么我建议使用MPI-IO(作为MPI2的一部分,c.1996左右的标准):很好的参考是:

在我们的中心,我们有第一部分,我认为这很好:

上面代码的MPI IOed版本如下:

#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>

int main(int argc, char** argv) {

    int rank, np;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &np);

    const int filesize = 48*1048576;  //input filesize 48MB
    const int ndoubles = filesize/(sizeof(double)*np);
    double *localdata = malloc(ndoubles*sizeof(double));

    /* create a type which describes our view of the file --
     * in particular, just our subarray of the global array
     */
    int globalsizes[1] = {filesize};
    int localsizes[1] = {ndoubles};
    int starts[1] = {ndoubles*rank};

    MPI_Datatype fileview;
    MPI_Type_create_subarray(1, globalsizes, localsizes, starts, MPI_ORDER_C, MPI_DOUBLE, &fileview);
    MPI_Type_commit(&fileview);

    /* read in only our data */
    MPI_File fpa;
    MPI_Status status;
    MPI_File_open(MPI_COMM_WORLD, "512_featurevec.out", MPI_MODE_RDONLY, MPI_INFO_NULL, &fpa);

    /* note could use MPI_File_seek instead of file set view */
    MPI_File_set_view(fpa, (MPI_Offset)0, MPI_DOUBLE, fileview, "native", MPI_INFO_NULL);
    MPI_File_read_all(fpa, localdata, ndoubles, MPI_DOUBLE, &status);
    MPI_File_close(&fpa);

    /* write out data - it will have same layout, we're just writing instead of erading*/

    MPI_File_open(MPI_COMM_WORLD, "output.dat", MPI_MODE_WRONLY|MPI_MODE_CREATE, MPI_INFO_NULL, &fpa);

    /* note could use MPI_File_seek instead of file set view */
    MPI_File_set_view(fpa, (MPI_Offset)0, MPI_DOUBLE, fileview, "native", MPI_INFO_NULL);
    MPI_File_write_all(fpa, localdata, ndoubles, MPI_DOUBLE, &status);
    MPI_File_close(&fpa);

    free(localdata);
    MPI_Type_free(&fileview);
    MPI_Finalize();

    return 0;
}
#包括
#包括
#包括
int main(int argc,字符**argv){
整数秩,np;
MPI_Init(&argc,&argv);
MPI通信等级(MPI通信世界和等级);
MPI通信大小(MPI通信世界和np);
const int filesize=48*1048576;//输入文件大小48MB
const int ndoubles=filesize/(双精度大小)*np;
double*localdata=malloc(ndoubles*sizeof(double));
/*创建一个描述文件视图的类型--
*特别是我们的全局数组的子数组
*/
int globalsizes[1]={filesize};
int localsize[1]={ndoubles};
int开始[1]={ndoubles*rank};
MPI_数据类型文件视图;
MPI\u类型\u创建\u子阵列(1、全局大小、本地大小、开始、MPI\u顺序、MPI\u双精度和文件视图);
MPI_类型_提交(&fileview);
/*只读取我们的数据*/
MPI_文件fpa;
MPI_状态;
MPI_文件打开(MPI_COMM_WORLD,“512_featurevec.out”、MPI_MODE_RDONLY、MPI_INFO_NULL和fpa);
/*注意:可以使用MPI_文件搜索而不是文件集视图*/
MPI文件集视图(fpa,(MPI偏移量)0,MPI双精度,文件视图,“本机”,MPI信息为空);
MPI文件读取全部(fpa、本地数据、ndoubles、MPI DOUBLE和状态);
MPI文件关闭(&fpa);
/*写出数据-它将有相同的布局,我们只是写而不是删除*/
MPI_文件打开(MPI_COMM_WORLD,“output.dat”,MPI_MODE_WRONLY,MPI_MODE_CREATE,MPI_INFO_NULL,&fpa);
/*注意:可以使用MPI_文件搜索而不是文件集视图*/
MPI文件集视图(fpa,(MPI偏移量)0,MPI双精度,文件视图,“本机”,MPI信息为空);
MPI文件写入全部(fpa、本地数据、ndoubles、MPI DOUBLE和状态);
MPI文件关闭(&fpa);
免费(本地数据);
无MPI类型(文件视图和文件视图);
MPI_Finalize();
返回0;
}

请不要投射malloc()返回的指针。你根本不需要触摸它,如果你这样做,你可能会允许出现错误。我很快就想测量I/O的加速,因此我尝试了并行化fwrite,正如我所展示的。但我同意,MPI_IO绝对是一种更好的方式。你可以使用MPI_File_seek(或MPI_File_write_at)以一种与你已经得到的非常相似的方式,它将具有更好的语义(例如,如果其他人移动文件指针,它不会做出奇怪的行为…)谢谢你的这篇文章,在我读这篇文章之前,我一直在挠头,没有取得任何进展。太简单了。