2010-02-14 5 views
1

J'essaie d'exécuter ce code Fortran MPI. Il y a plusieurs problèmes:MPI Fortran Code Problème

1) quand j'exécute ce code je m'attends à ce que le programme écrive 'Entrez le nombre d'intervalles: (0 quitte)' à l'écran puis demandez-moi n. Au lieu de cela, il me demande d'abord !!! Pourquoi? 2) Si je ne commente pas la ligne 'goto 10', le programme ne cesse de me demander pour toujours et ne me montre rien d'autre !!! 3) Si je commente 'goto 10', le programme me demande n, puis écrit les résultats. Mais, le problème est chaque fois que le programme écrit une partie du résultat et non les résultats complets. Il tronque la sortie !! ci-dessous sont de sortie pour trois fois de suite j'ai couru le programme:

> mpiexec -n 40 ./a.out 
10000000 
Enter the number of intervals: (0 quits) 
pi is 3.14159265358978  Error is 1.287858708565182E-014 
time is 1.687502861022949E-002 seconds 

> mpiexec -n 40 ./a.out 
10000000 
Enter the number of intervals: (0 quits) 
pi is 3.14159265358978  Error is 1.287858708565182E-014 
time is 1.68750286102 

> mpiexec -n 40 ./a.out 
10000000 
Enter the number of intervals: (0 quits) 
pi is 3.14159265358978  Error is 1.287858708565182E-014 
time is 1.687502861022949E-002 se 

Quelqu'un a une idée de ce qui se passe? J'apprécie votre aide à l'avance.

 program main 
     use mpi 
     double precision starttime, endtime 
     double precision PI25DT 
     parameter  (PI25DT = 3.141592653589793238462643d0) 
     double precision mypi, pi, h, sum, x, f, a 
     double precision starttime, endtime 
     integer n, myid, numprocs, i, ierr 

     f(a) = 4.d0/(1.d0 + a*a) ! function to integrate 

     call MPI_INIT(ierr) 
     call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierr) 
     call MPI_COMM_SIZE(MPI_COMM_WORLD, numprocs, ierr) 

10 if (myid .eq. 0) then 
     print *, 'Enter the number of intervals: (0 quits) ' 
     read(*,*) n 
     endif 
     starttime = MPI_WTIME() 
!         broadcast n 
     call MPI_BCAST(n,1,MPI_INTEGER,0,MPI_COMM_WORLD,ierr) 
!         check for quit signal 
     if (n .le. 0) goto 30 
!         calculate the interval size 
     h = 1.0d0/n 
     sum = 0.0d0 
     do 20 i = myid+1, n, numprocs 
     x = h * (dble(i) - 0.5d0) 
     sum = sum + f(x) 
20 continue 
     mypi = h * sum 
!         collect all the partial sums 
     call MPI_REDUCE(mypi,pi,1,MPI_DOUBLE_PRECISION,MPI_SUM,0, & 
         MPI_COMM_WORLD,ierr) 
!         node 0 prints the answer. 
     endtime = MPI_WTIME() 
     if (myid .eq. 0) then 
     print *, 'pi is ', pi, 'Error is ', abs(pi - PI25DT) 
     print *, 'time is ', endtime-starttime, ' seconds' 
     endif 
     go to 10 
30 call MPI_FINALIZE(ierr) 
     stop 
     end 
+0

papier suivant dans votre liste de lecture devrait être « Un cas contre le GO TO Déclaration » de la célèbre Dijkstra. – Wildcat

Répondre

1

Vous devez explicitement vider votre sortie. Je ne me souviens pas si fortran a la fonction flush standard, si flush ne fonctionne pas, essayez flush_.

Fondamentalement, ce qui se passe, votre processus zéro sortie de tampons, et à moins que le dire explicitement à afficher, vous finissez par une étoffe drôle

+0

Merci, ça a marché! Mais comment cela résout-il le problème du goto? Avez-vous une idée? – Bahman

+1

Fortran 2003 inclut une instruction de vidage. De nombreux compilateurs l'incluent déjà. Certains l'ont eu ou des variations avant la norme de langue 2003. Je n'ai jamais eu à l'utiliser. Est-ce nécessaire à cause de MPI? –

+0

@ Flash Bahman s'assure que les tampons de sortie sont forcés à imprimer avant la fin du programme. La sortie Fortran et C (mpi est écrit en c) interagissent de manière étrange. – Anycorn

3

Ce programme est conçu en boucle via à la fin « goto 10 ». La seule façon de sortir de ceci est que n ait une valeur < = 0, ce qui activera le "goto 30" et dépassera le "goto 10". Des indices supplémentaires que ceci est l'intention sont le commentaire "vérifier le signal de sortie" et que l'invite pour l'entrée de n inclut "(0 quitte)". Essayez donc d'entrer 0!

Ce n'est pas un bon exemple de Fortran moderne. Malgré l'utilisation claire d'un compilateur Fortran 90 ou plus récent (l'instruction "use" le montre), il est écrit dans le style de FORTRAN 77 ou plus tôt. Mise en page à source fixe, avec les lignes source commençant apparemment dans la colonne 7. Commentez les caractères dans la première colonne (l'ancien Fortran nécessitait un C dans la première colonne). "Double precision". Utilisation intensive de gotos pour la logique du programme. (À mon avis, et d'autres peuvent être en désaccord, il y a une place pour la déclaration goto, mais pas pour le flux de contrôle de base d'un programme.) Obsolète Fortran (à mon avis).

La façon Fortran moderne d'exprimer le débit de base:

MainLoop: do 
    ..... 
    if (n .le. 0) exit MainLoop 
    .... 
end do MainLoop