Je me bats depuis quelques jours avec un appel MPI_REDUCE dans un code de modèle de transport atmosphérique gfortran, ayant de bons paramètres d'entrée, mais retournant des résultats très déraisonnables dans le recvbuf du maître. Je suis en mesure de reproduire le problème dans un exemple simple, comme suit:MPI_REDUCE renvoie une mauvaise réponse pour 1000x1000x6 REAL array
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
Il retourne:
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 « devrait » être montrant 18.000.000,0 comme SUM (v) dans le dernier ligne.
Si je mets le paramètre nz dans le code de 6 à 5, l'exécution produit des résultats corrects. Ce qui est vraiment déroutant, c'est qu'il se comporte de la sorte, renvoyant la même somme de valeurs réduites sur a) une instance AWS EC2 avec gfortran 5.3 et openmpi, b) gfortran 5.4 avec mpich, et c) un gfortran 4.4 avec openmpi.
Si je change le type de tableau en DOUBLE PRECISION (aussi bien que cela spécifie que dans l'appel MPI_REDUCE) cela fonctionne bien, même pour des tableaux beaucoup plus grands. Si j'utilise REAL4 plutôt que REAL, cela produit les mêmes mauvais résultats. Je sais que cela doit être simple et que je suis un vrai idiot ici, mais je ne comprends tout simplement pas cela. J'ai lu quelques suggestions que ma taille de tampon doit être une valeur entière inférieure à 2^31-1, mais c'est certainement le cas ici.
Fortran ne précise en effet pas comment «somme» fonctionne, mais simplement que le résultat «a une valeur égale à une approximation dépendant du processeur de la somme». Différents compilateurs traitent cela comme un problème de qualité de mise en œuvre, comme on peut le voir dans [cette autre question] (https://stackoverflow.com/q/25316371). – francescalus