Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 使用MPI RMA写入阵列_Arrays_Fortran_Mpi - Fatal编程技术网

Arrays 使用MPI RMA写入阵列

Arrays 使用MPI RMA写入阵列,arrays,fortran,mpi,Arrays,Fortran,Mpi,我想用累加(MPI RMA)写入一个数组,该数组可以通过窗口访问。为了便于检查,我将数组索引写入每个单元格。问题是,开始似乎总是正确的,但最后有时会出现错误的值:不是它的位置值,而是将最后一个条目设置为最终索引 我的代码: PROGRAM main USE mpi IMPLICIT NONE REAL*8, PARAMETER :: prec = 1d-13 REAL(kind(prec)

我想用累加(MPI RMA)写入一个数组,该数组可以通过窗口访问。为了便于检查,我将数组索引写入每个单元格。问题是,开始似乎总是正确的,但最后有时会出现错误的值:不是它的位置值,而是将最后一个条目设置为最终索引

我的代码:

PROGRAM main         
     USE mpi
     IMPLICIT NONE

     REAL*8, PARAMETER                         :: prec = 1d-13
     REAL(kind(prec)),ALLOCATABLE,DIMENSION(:) :: speicher1D
     INTEGER                                   :: stelle, ierror
     INTEGER                                   :: ix,iy,iz,nz,i
     !--------------------------------------------------------------
     !---------------MPI-Variablen----------------------------------
     !--------------------------------------------------------------
     INTEGER                        :: myRank               = 0
     INTEGER                        :: numProcs             = 1
     INTEGER, PARAMETER             :: masterProc           = 0

     INTEGER                        :: s3Win1D,s3Win3D
     INTEGER                        :: startIndex, endIndex
     INTEGER(KIND=MPI_ADDRESS_KIND) :: sizeOfSchritt3D1
     INTEGER(KIND=MPI_ADDRESS_KIND) :: s3TargetDisp
     INTEGER                        :: prec_mpi, sizeOfprec_mpi
     !--------------------------------------------------------------
     !--------------MAIN-PROGRAM------------------------------------
     !--------------------------------------------------------------        


     !----MPI-Initialisierung----
     CALL MPI_INIT(ierror)
     CALL MPI_COMM_RANK(MPI_COMM_WORLD, myRank,ierror)
     CALL MPI_COMM_SIZE(MPI_COMM_WORLD,numProcs, ierror)

     !Create new MPI-datatype
     CALL MPI_TYPE_CREATE_F90_REAL(KIND(prec), MPI_UNDEFINED, prec_mpi,ierror)         
     CALL MPI_TYPE_SIZE(prec_mpi, sizeOfprec_mpi,ierror)

     nz                     = 3
     sizeOfSchritt3D1       = sizeOfprec_mpi*(nz*2+1)**3

     ALLOCATE(speicher1D((nz*2+1)**3))
     !------------MPI-RMA-Initialisierung--------------------------
     CALL MPI_WIN_CREATE(speicher1D, sizeOfSchritt3D1, sizeOfprec_mpi,MPI_INFO_NULL,MPI_COMM_WORLD,s3Win1D, ierror)
     !Determine each proc's area
     startIndex  = (nz*2+1)/numProcs*myRank-nz
     endIndex    = (nz*2+1)/numProcs*(myRank+1)-nz-1
     IF(myRank+1 .EQ. numProcs) THEN
        endIndex = nz
     END IF

     speicher1D          = 0.0d0  
     CALL MPI_BARRIER(MPI_COMM_WORLD,ierror)
     CALL MPI_WIN_FENCE(0,s3Win1D, ierror)
     DO iz=startIndex, endIndex
       DO iy=-nz,nz
         DO ix=-nz,nz
           stelle = 1 + (iz+nz)*(2*nz+1)**2 + (iy+nz)*2*nz+1)+ (ix+nz)
           s3targetDisp = stelle-1
           !WRITE(*,*) "Rank", myRank,"s3targetDisp: ",s3targetDisp, "index: ",stelle
           !1D
           CALL MPI_ACCUMULATE(REAL(stelle,kind(prec)), 1, prec_mpi, masterProc, s3targetDisp,1,prec_mpi, MPI_SUM,s3Win1D, ierror)
         END DO 
       END DO
     END DO     
     CALL MPI_WIN_FENCE(0,s3Win1D, ierror)
     CALL MPI_BARRIER(MPI_COMM_WORLD, ierror)
     DO i = 1,(nz*2+1)**3
       IF(myRank .EQ. masterProc) THEN
         WRITE(*,*) "Index: ",i,", entry: ",speicher1D(i)
       END IF
     END DO
     DEALLOCATE(speicher1D)

     CALL MPI_WIN_FREE(s3Win1D, ierror)
     CALL MPI_FINALIZE(ierror)
  END PROGRAM main
我定义了一个新的MPI数据类型prec_MPI,并使用了三个嵌套循环,因为我需要将此模式用于另一个(更大的)程序。使用整数写入此双精度数组也是有意的

我得到的一个错误输出结果如下:

[...]
 Index:          250 , entry:    250.000000000000     
 Index:          251 , entry:    251.000000000000     
 Index:          252 , entry:    252.000000000000     
 Index:          253 , entry:    253.000000000000     
 Index:          254 , entry:    254.000000000000     
 Index:          255 , entry:    255.000000000000     
 Index:          256 , entry:    256.000000000000     
 Index:          257 , entry:    257.000000000000     
 Index:          258 , entry:    258.000000000000     
 Index:          259 , entry:    259.000000000000     
 Index:          260 , entry:    260.000000000000     
 Index:          261 , entry:    261.000000000000     
 Index:          262 , entry:    262.000000000000     
 Index:          263 , entry:    263.000000000000     
 Index:          264 , entry:    264.000000000000     
 Index:          265 , entry:    265.000000000000     
 Index:          266 , entry:    266.000000000000     
 Index:          267 , entry:    267.000000000000     
 Index:          268 , entry:    268.000000000000     
 Index:          269 , entry:    269.000000000000     
 Index:          270 , entry:    270.000000000000     
 Index:          271 , entry:    271.000000000000     
 Index:          272 , entry:    272.000000000000     
 Index:          273 , entry:    273.000000000000     
 Index:          274 , entry:    274.000000000000     
 Index:          275 , entry:    275.000000000000     
 Index:          276 , entry:    302.000000000000     
 Index:          277 , entry:    303.000000000000     
 Index:          278 , entry:    304.000000000000     
 Index:          279 , entry:    305.000000000000     
 Index:          280 , entry:    306.000000000000     
 Index:          281 , entry:    308.000000000000     
 Index:          282 , entry:    310.000000000000     
 Index:          283 , entry:    313.000000000000     
 Index:          284 , entry:    316.000000000000     
 Index:          285 , entry:    319.000000000000     
 Index:          286 , entry:    322.000000000000     
 Index:          287 , entry:    325.000000000000     
 Index:          288 , entry:    329.000000000000     
 Index:          289 , entry:    332.000000000000     
 Index:          290 , entry:    335.000000000000     
 Index:          291 , entry:    338.000000000000     
 Index:          292 , entry:    341.000000000000     
 Index:          293 , entry:    342.000000000000     
 Index:          294 , entry:    343.000000000000     
 Index:          295 , entry:    343.000000000000     
 Index:          296 , entry:    343.000000000000     
 Index:          297 , entry:    343.000000000000     
 Index:          298 , entry:    343.000000000000     
 Index:          299 , entry:    343.000000000000     
 Index:          300 , entry:    343.000000000000     
 [...]   
 Index:          341 , entry:    343.000000000000     
 Index:          342 , entry:    343.000000000000     
 Index:          343 , entry:    343.000000000000 

为什么条目会有这样的跳跃(在本例中是在索引275之后)?当我在嵌套循环中使用
write
检查stelle和s3TargetDisp的值时,我觉得它们没有问题。可能是同步有问题……但嵌套循环中的数据只是累加(没有混合的RMA/本地数据),并且有一个封闭的围栏。

很抱歉,我修复了它。这不是一个正确的MPI程序。RMA通信调用是非阻塞的,必须这样处理:“RMA调用的本地通信缓冲区不应更新,并且在RMA调用后,在操作在原点完成之前,get调用的本地通信缓冲区不应访问。”(MPI 3.1,第11.3节)在执行同步操作之前,您正在多次调用
MPI\u acculate
,很可能是使用同源缓冲区—一个临时变量,编译器将转换结果存储在该变量中。
real*8
不是有效的Fortran,也从来不是任何ISO Fortran标准的一部分。@jlokimlin感谢您的提示,我会考虑的。“你是对的,谢谢你。我在内部循环的末尾添加了一个
MPI\u WIN\u FENCE
。除了调用
MPI\u WIN\u Fence
,是否有更好的可能性确保我可以重用缓冲区?现在有很多同步,由于我的原始负载分布,我还需要在循环外添加额外的同步,以匹配上一个进程的同步…很抱歉,我修复了它。这不是正确的MPI程序。RMA通信调用是非阻塞的,必须这样处理:“RMA调用的本地通信缓冲区不应更新,并且在RMA调用后,在操作在原点完成之前,get调用的本地通信缓冲区不应访问。”(MPI 3.1,第11.3节)在执行同步操作之前,您正在多次调用
MPI\u acculate
,很可能是使用同源缓冲区—一个临时变量,编译器将转换结果存储在该变量中。
real*8
不是有效的Fortran,也从来不是任何ISO Fortran标准的一部分。@jlokimlin感谢您的提示,我会考虑的。“你是对的,谢谢你。我在内部循环的末尾添加了一个
MPI\u WIN\u FENCE
。除了调用
MPI\u WIN\u Fence
,是否有更好的可能性确保我可以重用缓冲区?现在有很多同步,由于我的基本负载分布,我还需要在循环之外添加额外的同步,以匹配上一个进程的同步。。。