1

私はこれをするのが好きです:

program main
  implicit none
  integer l
  integer, allocatable, dimension(:) :: array

  allocate(array(10))

  array = 0

  !$omp parallel do private(array)
  do l = 1, 10
    array(l) = l
  enddo
  !$omp end parallel do

  print *, array

  deallocate(array)

end

しかし、エラーメッセージが表示されます:

* glibc が検出されました * ./a.out: munmap_chunk(): 無効なポインター: 0x00007fff25d05a40 *

インテル フォーラムでのいくつかの議論によると、これは ifort のバグのようですが、私が使用しているバージョン (11.1.073 - Linux) では解決されるはずです。これは、私のコードを大幅に縮小したバージョンです。残念ながら、回避策として静的配列を使用することはできません。

印刷をループに入れると、他のエラーが発生します。

* glibc が検出されました./a.out: 二重解放または破損 (out): 0x00002b22a0c016f0 * *

4

3 に答える 3

1

コードを ifort と openmp で実行したところ、0d0 が吐き出されました。実行を手動で終了する必要がありました。期待される出力は何ですか? 私は、配列を不必要に動的に割り当てることは好きではありません。行列を何として割り当てるかはわかっているので、パラメータを作成して静的に実行するだけです。私はいくつかのものをいじり、この応答をいくつか編集します。

わかりましたので、ここに私の編集があります:

  program main
  implicit none

  integer :: l, j
  integer, parameter :: lmax = 15e3
  integer, parameter :: jmax = 25
  integer, parameter :: nk = 300
  complex*16, dimension(9*nk) :: x0, xin, xout
  complex*16, dimension(lmax) :: e_pump, e_probe
  complex*16 :: e_pumphlp, e_probehlp
  character*25 :: problemtype
  real*8 :: m

  ! OpenMP variables
  integer :: myid, nthreads, omp_get_num_threads, omp_get_thread_num

  x0 = 0.0d0

  problemtype = 'type1'
  if (problemtype .ne. 'type1') then
     write(*,*) 'Problem type not specified. Quitting'
     stop
  else
     ! Spawn a parallel region explicitly scoping all variables
     !$omp parallel 
        myid = omp_get_thread_num()
        if (myid .eq. 0) then
           nthreads = omp_get_num_threads()
           write(*,*) 'Starting program with', nthreads, 'threads'
        endif

        !$omp do private(j,l,m,e_pumphlp,e_probehlp,e_pump,e_probe)
        do j = 1, jmax - 1
           do l = 1, lmax

              call electricfield(0.0d0, 0.0d0, e_pumphlp, &
                                 e_probehlp, 0.0d0)
              !   print *, e_pumphlp, e_probehlp

              e_pump(l) = e_pumphlp
              e_probe(l) = e_probehlp
              print *, e_pump(l), e_probe(l)

           end do
        end do
     !$omp end parallel
  end if

  end program main

不要なため、モジュールの使用を削除したことに注意してください。サブルーチンを含む外部モジュールがあるので、それを外部サブルーチンにします。また、行列を静的に割り当てるように変更しました。Case ステートメントは、if ステートメントの凝った高価なバージョンです。あなたは1回ではなく15e3 * 25回ケーシングしていたので(高価です)、それらを外に移動しました。OpenMP 呼び出しを変更しましたが、意味的にのみ変更しました。OpenMP が実際に何をしているのかを理解できるように、いくつかの出力を示しました。

新しいサブルーチンは次のとおりです。

  subroutine electricfield(t, tdelay, e_pump, e_probe, phase)
  implicit none

  real*8, intent(in) :: t, tdelay
  complex*16, intent(out) :: e_pump, e_probe
  real*8, optional, intent (in) :: phase

  e_pump = 0.0d0
  e_probe = 0.0d0

  return

  end subroutine electricfield

その周りのモジュール シェルを削除し、変数名の一部を変更しました。Fortran では大文字と小文字が区別されないため、大文字を使用したり、最後まで繰り返さなければならないことで自分を苦しめたりしないでください。

これをコンパイルしました

ifort -o diffeq diffeq.f90 electricfield.f90 -openmp

そして一緒に走った

./diffeq > 出力

0 を吐くプログラムをキャッチし、使用していたスレッドの数を確認するには:

(0.000000000000000E+000,0.000000000000000E+000) (0.000000000000000E+000,0.000000000000000E+000) (0.000000000000000E+000,0.000000000000000E+000) (0.000000000000000E+000,0.000000000000000E+000) (0.000000000000000E+000, 0.000000000000000E+000) (0.000000000000000E+000,0.000000000000000E+000) (0.000000000000000E+000,0.000000000000000E+000) (0.000000000000000E+000,0.000000000000000E+000) (0.000000000000000E+000,0.000000000000000E+000) ( 0.000000000000000E+000,0.000000000000000E+000)
32スレッドでプログラムを起動
(0.000000000000000E+000,0.000000000000000E+000) (0.000000000000000E+000,0.000000000000000E+000) (0.000000000000000E+000,0.000000000000000E+000) (0.000000000000000E+000,0.000000000000000E+000) (0.000000000000000E+000, 0.000000000000000E+000) (0.000000000000000E+000,0.000000000000000E+000)

お役に立てれば!

于 2013-02-20T16:09:54.470 に答える
1

表示されているエラーは表示されませんでしたが、OpenMP 呼び出しでの配列のプライベート化に問題があります。

[mjswartz@666-lgn testfiles]$ vi array.f90  
[mjswartz@666-lgn testfiles]$ ifort -o array array.f90 -openmp  
[mjswartz@666-lgn testfiles]$ ./array 
           0           0           0           0           0           0
           0           0           0           0  
[mjswartz@666-lgn testfiles]$ vi array.f90  
[mjswartz@666-lgn testfiles]$ ifort -o array array.f90 -openmp  
[mjswartz@666-lgn testfiles]$ ./array 
           1           2           3           4           5           6
           7           8           9          10

最初の実行はプライベート アレイを使用し、2 回目はプライベート アレイを使用しません。

  program main
  implicit none

  integer l
  integer, allocatable, dimension(:) :: array

  allocate(array(10))

  !$omp parallel do 
  do l = 1, 10
    array(l) = l
  enddo

  print*, array

  deallocate(array)

  end program main
于 2013-02-20T16:42:57.873 に答える
0

OpenMP 3.0 の実装に関連するコンパイラのバグが発生しているようです。

コンパイラを更新できない場合は、アプローチを変更する必要があります。いくつかのオプションがあります。たとえば、割り当て可能な配列を共有し、ランクを 1 つ上げて、1 つのスレッドに割り当てることで、追加の次元の範囲がチーム内のワーカーの数になるようにすることができます。これらの配列への後続のすべての参照では、その追加ランクの添え字を omp チーム番号 (下限に使用したものに応じて + 1) にする必要があります。

並列コンストラクト (のみ) 内のプライベート割り当て可能配列の明示的な割り当てもオプションの場合があります。

于 2013-02-20T21:12:38.297 に答える