Pergunta

Estou tentando executar esse código MPI fortran. Existem vários problemas:

1) Quando executo este código, espero que o programa escreva 'Digite o número de intervalos: (0 desmaios)' para que eu me pergunte n. Em vez disso, me pergunta n primeiro !!! porque?

2) Se eu não comentar a linha 'Goto 10', o programa continua me perguntando n para sempre e não me mostra mais nada !!!

3) Se eu comentar 'Goto 10', o programa me pergunte e depois gravará resultados. Mas, o problema é sempre que o programa escreve parte do resultado, não os resultados completos. Trunca a saída !! Abaixo estão a produção por três vezes consecutivos, executei o programa:

> 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

Alguém tem alguma ideia do que está acontecendo? Agradeço sua ajuda com antecedência.

      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
Foi útil?

Solução

Você precisa lavar explicitamente sua saída. Não me lembro se o Fortran tem função de descarga padrão, se não funcionar, tente Flush_.

Basicamente, o que acontece, seu processo zero buffers de saída e, a menos que o explicitamente diga para exibir, você acaba uma coisa engraçada

Outras dicas

Este programa foi projetado para fazer loop através do "Goto 10" no final. A única maneira de romper com isso é que N tenha um valor <= 0, que ativará o "Goto 30" e o ramo além do "Goto 10". Pistas adicionais de que essa é a intenção são o comentário "Verifique o sinal de desativação" e que o prompt para a entrada de n inclui "(0 desmaios)". Então tente inserir 0!

Este não é um bom exemplo de fortran moderno. Apesar de claramente usar um compilador Fortran 90 ou mais recente (a declaração "Uso" mostra isso), ele é escrito no estilo do Fortran 77 ou anterior. Layout de código fixo, com as linhas de origem aparentemente começando na coluna 7. Comente os caracteres na primeira coluna (o antigo fortran exigiu um C na primeira coluna). "Dupla precisão". Uso pesado de Gotos para a lógica do programa. (Na minha opinião, e outros podem discordar, há um lugar para a declaração de goto, mas não para o fluxo de controle básico de um programa.) Obsolete fortran (na minha opinião).

A maneira moderna fortran de expressar o fluxo básico:

MainLoop: do
   .....
   if (n .le. 0) exit MainLoop
   ....
end do MainLoop
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top