使用MPI_Type_create_subarray写入分布式数据出现无效数据的修复咨询
解决MPI分布式数据写入单个文件时出现NaN/垃圾数据的问题
看起来你的问题主要来自两个关键错误,让我们一步步拆解并修复:
1. 最严重的问题:MPI_Status变量声明错误
在Fortran中,MPI_Status类型并不是单个整数,而是一个大小为MPI_STATUS_SIZE的数组。你的代码里把istatus声明成了单个integer:
integer ierr,istatus,myrank,NPROCS,SUBARRAY,NUM,fh
当你调用MPI_File_write_all时,MPI会尝试写入这个变量的内存空间之外的区域,导致内存越界,破坏程序的状态(比如子数组类型的元数据),最终写入垃圾数据到文件中。
修复方法:
把istatus声明为符合要求的数组:
integer ierr, myrank, NPROCS, SUBARRAY, NUM, fh integer istatus(MPI_STATUS_SIZE)
2. 次要问题:MPI_File_write_all的参数不匹配
你当前使用MPI_DOUBLE_PRECISION作为写入的数据类型,同时传入num(子数组元素个数)作为count。虽然理论上如果buf的内存布局和subarray类型完全一致时这种写法能工作,但更规范且不易出错的方式是直接使用你创建的SUBARRAY类型作为写入的数据类型,count设为1——因为SUBARRAY已经完整描述了你的子数组的大小和内存布局。
修复方法:
修改MPI_File_write_all的调用:
call mpi_file_write_all(fh, buf, 1, SUBARRAY, istatus, ierr)
这样MPI会自动将你的buf数组作为一个完整的子数组写入文件对应位置,无需手动计算元素个数。
3. 额外检查点
- 确保运行程序时指定的进程数是5(
mpiexec -n 5 ./your_program),因为你的代码只处理了rank 0到4的情况,多余的进程会因为未分配buf而崩溃。 - 确认所有进程的
buf维度和SUBSIZE严格匹配:比如rank 2的SUBSIZE是(2,1,2),buf分配为(0:1,1,0:1),这是正确的;其他进程的维度也都没问题。
修改后的完整代码
program test use mpi implicit none integer ierr, myrank, NPROCS, SUBARRAY, NUM, fh integer istatus(MPI_STATUS_SIZE) INTEGER START(0:2), GSIZE(0:2), SUBSIZE(0:2), i,j,k real*8, dimension(:,:,:), pointer:: buf real*8 f(0:9) call mpi_init(ierr) call mpi_comm_size(MPI_COMM_WORLD, NPROCS, IERR) CALL MPI_COMM_RANK(MPI_COMM_WORLD, MYRANK, IERR) GSIZE(0)=2 GSIZE(1)=5 GSIZE(2)=5 IF(MYRANK.EQ.0)THEN allocate(buf(0:1,0:1,0:1)) START(0)=0 START(1)=0 START(2)=0 SUBSIZE(0)=2 SUBSIZE(1)=2 SUBSIZE(2)=2 NUM=2*2*2 buf=real(myrank) ELSEIF(MYRANK.EQ.1)THEN allocate(buf(0:1,0:1,0:1)) START(0)=0 START(1)=2 START(2)=0 SUBSIZE(0)=2 SUBSIZE(1)=2 SUBSIZE(2)=2 NUM=2*2*2 buf=real(myrank) ELSEIF(MYRANK.EQ.2)THEN allocate(buf(0:1,1,0:1)) START(0)=0 START(1)=4 START(2)=0 SUBSIZE(0)=2 SUBSIZE(1)=1 SUBSIZE(2)=2 NUM=2*1*2 buf=real(myrank) ELSEIF(MYRANK.EQ.3)THEN allocate(buf(0:1,0:4,0:1)) START(0)=0 START(1)=0 START(2)=2 SUBSIZE(0)=2 SUBSIZE(1)=5 SUBSIZE(2)=2 NUM=2*5*2 buf=real(myrank) ELSEIF(MYRANK.EQ.4)THEN allocate(buf(0:1,0:4,1)) START(0)=0 START(1)=0 START(2)=4 SUBSIZE(0)=2 SUBSIZE(1)=5 SUBSIZE(2)=1 NUM=2*5*1 buf=real(MYRANK) ENDIF CALL MPI_TYPE_CREATE_SUBARRAY(3, GSIZE, SUBSIZE, START, & MPI_ORDER_fortran, MPI_DOUBLE_PRECISION, SUBARRAY, IERR) CALL MPI_TYPE_COMMIT(SUBARRAY, IERR) call mpi_file_open(mpi_comm_world, 'file', & mpi_mode_wronly+mpi_mode_create, mpi_info_null, fh, ierr) call mpi_file_set_view(fh, 0_mpi_offset_kind, & mpi_double_precision, subarray, 'native', mpi_info_null, ierr) call mpi_file_write_all(fh, buf, 1, SUBARRAY, istatus, ierr) call mpi_file_close(fh, ierr) CALL MPI_FINALIZE(IERR) END
经过这些修改后,你的程序应该能正确将所有分布式数据写入单个文件,不会再出现NaN或垃圾数据。
内容的提问来源于stack exchange,提问作者chan lee
相关产品推荐
相关产品推荐

