1

この MPI Fortran コードを実行しようとしています。いくつかの問題があります:

1)このコードを実行すると、プログラムが「間隔の数を入力してください:(0終了)」と画面に書き込み、nを尋ねます。代わりに、最初に n と尋ねます!!! なぜ?

2) 'goto 10' という行をコメントアウトしないと、プログラムは永遠に n を尋ね続け、他に何も表示しません!!!

3) 'goto 10' をコメントアウトすると、プログラムは私に尋ね、結果を書き込みます。しかし、プログラムが完全な結果ではなく結果の一部を書き込むたびに問題が発生します。出力を切り捨てます!! 以下は、プログラムを3回連続して実行したときの出力です。

> 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

誰が何が起こっているのか知っていますか?よろしくお願いします。

      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
4

2 に答える 2

3

このプログラムは、最後の「goto 10」を介してループするように設計されています。これを打破する唯一の方法は、n の値を <= 0 にすることです。これにより、「goto 30」がアクティブになり、「goto 10」を超えて分岐します。これが意図であるという追加の手がかりは、「終了シグナルの確認」というコメントと、n の入力のプロンプトに「(0 終了)」が含まれていることです。では、0 を入力してみてください。

これは現代の Fortran の良い例ではありません。明らかに Fortran 90 以降のコンパイラを使用しているにもかかわらず (「use」ステートメントがこれを示しています)、FORTRAN 77 以前のスタイルで記述されています。固定ソース レイアウト。ソース行は明らかに 7 列目から始まります。最初の列に文字をコメントします (古い Fortran では最初の列に C が必要でした)。"倍精度"。プログラム ロジックの goto の多用。(私の意見では、他の人は同意しないかもしれませんが、goto ステートメントの場所はありますが、プログラムの基本的な制御フローの場所はありません。) 廃止された Fortran (私の意見では)。

基本的な流れを表現する最新の Fortran の方法:

MainLoop: do
   .....
   if (n .le. 0) exit MainLoop
   ....
end do MainLoop
于 2010-02-15T03:10:18.753 に答える
1

出力を明示的にフラッシュする必要があります。fortran に標準のフラッシュ機能があるかどうか覚えていません。フラッシュが機能しない場合は、flush_ を試してください。

基本的に何が起こるか、あなたのプロセスはゼロバッファ出力を出力し、明示的に表示するように指示しない限り、面白いものになります

于 2010-02-14T18:09:01.890 に答える