MPI_REDUCE返回错误的答案1000x1000x6 REAL数组

问题描述:

我已经争取了两天,在一个gfortran大气输送模式代码MPI_REDUCE调用,具有良好的输入参数,但返回在主人的recvbuf非常不合理的结果。我已经能够复制一个简单的例子问题,具体如下:MPI_REDUCE返回错误的答案1000x1000x6 REAL数组

PROGRAM TEST 

    USE mpi 

    IMPLICIT NONE 

    INTEGER my_rank, size, ierror 
    INTEGER, PARAMETER :: nx=1000, ny=1000, nz=6 
    INTEGER :: buffsize 

    REAL, DIMENSION(nx, ny, nz) :: u, v 

    call MPI_INIT(ierror) 
    call MPI_COMM_SIZE(MPI_COMM_WORLD, size, ierror) 
    call MPI_COMM_RANK(MPI_COMM_WORLD, my_rank, ierror) 

    PRINT *, 'my_rank, size: ', my_rank, size 

    buffsize = nx*ny*nz 

    u = my_rank + 1 

    PRINT *, 'PE: ', my_rank, ', Before reduce, SHAPE(u): ', SHAPE(u) 
    PRINT *, 'PE: ', my_rank, ', Before reduce, SUM(u): ', SUM(u) 

    CALL MPI_REDUCE(u, v, buffsize, MPI_REAL, & 
&     MPI_SUM, 0, MPI_COMM_WORLD, ierror) 

    CALL MPI_BARRIER(MPI_COMM_WORLD, ierror) 

    PRINT *, 'PE: ', my_rank, ', after reduce, ierror: ', ierror 
    PRINT *, 'PE: ', my_rank, ', after reduce, SUM(u): ', SUM(u) 
    PRINT *, 'PE: ', my_rank, ', after reduce, SUM(v): ', SUM(v) 

    CALL MPI_FINALIZE(ierror) 

END PROGRAM test 

它返回:

mpirun -np 2 ./test3 
my_rank, size:   0   2 
my_rank, size:   1   2 
PE:   1 , Before reduce, SHAPE(u):   1000  1000   6 
PE:   0 , Before reduce, SHAPE(u):   1000  1000   6 
PE:   0 , Before reduce, SUM(u): 6000000.00  
PE:   1 , Before reduce, SUM(u): 12000000.0  
PE:   0 , after reduce, ierror:   0 
PE:   1 , after reduce, ierror:   0 
PE:   1 , after reduce, SUM(u): 12000000.0  
PE:   0 , after reduce, SUM(u): 6000000.00  
PE:   1 , after reduce, SUM(v): 0.00000000  
PE:   0 , after reduce, SUM(v): 18407592.0  

PE0“应该”显示18000000.0作为最后SUM(五)线。

如果我在代码6到5中设置nz参数,则运行会生成正确的结果。什么是真正令人困惑的是,它的行为这种方式,与gfortran 5.3和的openmpi在返回减少值相同总和)的AWS EC2实例,B)我的笔记本电脑的gfortran 5.4 MPICH,以及c)工作站的gfortran 4.4的openmpi。

如果我改变阵列的类型为双精度(水井作为指定在MPI_REDUCE调用)能正常工作,甚至更大的阵列。如果我使用REAL4而不是REAL,它会产生相同的错误结果。

我知道这必须是简单的,并且我是这里真正的白痴,但我只是不明白这一点。我读过一些建议,我的缓冲区大小需要是小于2^31-1的整数值,但在这里肯定是这种情况。

这有什么好做MPI,它只是一个求和精度问题:

PROGRAM TEST 
    IMPLICIT NONE 
    INTEGER, PARAMETER :: nx=1000, ny=1000, nz=6 
    REAL, DIMENSION(nx, ny, nz) :: u 
    u = 3 
    PRINT *, SUM(u) 
END PROGRAM test 

返回相同的结果。如果给一个小数加上一个大数,那么可能会出现四舍五入的问题,在许多小数的总和中,这种影响可能会累积到一个显着的误差。有求和算法来防止这种效果,像Kahan summation,显然是Fortran语言的SUM未实现这种方式。

+4

Fortran语言确实没有规定如何'sum'的作品,仅仅是这个结果“有等于处理器相关逼近总和值”。不同的编译器将此视为实现质量问题,如[另一个问题]中所示(https://*.com/q/25316371)。 – francescalus