1

並列部分がある Fortran コードがあります。正常にコンパイルされgfortranますが、実行するとセグメンテーション違反が発生します。シリアル コンパイルされた実行ファイルには、エラーは表示されません。また、非常に小さな入力行列 (rho1 と rho2) を使用して並列プログラムを調べ、段階的なパラメーターをテストしました。過失はありませんでした。私の理解が正しければ、変数を と決定した場合、PRIVATEを使用する必要はありません $OMP ATOMIC。ここで、行列 rho1 と rho2 の次元は約 15,000,000 です。コードの並列部分は次のとおりです。

!$OMP PARALLEL DO ORDERED DEFAULT(PRIVATE)
  do ix = 1 , nx
    do iy = 1 , ny
      do iz = 1 , nz
         k = iz + (iy-1) * nz + (ix-1) * ny * nz
         if (rho1(k) .GT. 0.d0) then
           x1 = x0 + ((ix-1) * dx)
           y1 = y0 + ((iy-1) * dy)
           z1 = z0 + ((iz-1) * dz)
           rr = (x1-xa)**2 + (y1-ya)**2 + (z1-za)**2
           r1a = dsqrt (rr)
           rr = (x1-xb)**2 + (y1-yb)**2 + (z1-zb)**2
           r1b = dsqrt (rr)
           if (r1a == 0.d0) Vnuc = (rho1(k) * Znb)/r1b
           if (r1b == 0.d0) Vnuc = (rho1(K) * Zna)/r1a
           if (r1a .GT. 0.d0 .AND. r1b .GT. 0.d0) then
             Vnuc = (rho1(k) * Zna)/r1a + (rho1(K) * Znb)/r1b
           endif
           Ve = 0
           !$OMP ORDERED
           j = 1
           do jx = 1 , nx
            do jy = 1 , ny
             do jz = 1 , nz
               if (rho2(j) .GT. 0.d0) then
                x2 = x0 + ((jx-1) * dx)
                y2 = y0 + ((jy-1) * dy)
                z2 = z0 + ((jz-1) * dz)
                rr= (x1-x2)**2 + (y1-y2)**2 + (z1-z2)**2
                r12 = dsqrt (rr)
                if (r12 .GT. 0.d0) then
                 Ve = Ve + (rho1(k)*rho2(j))/r12
                endif
               endif
               j = j + 1
             enddo
            enddo
           enddo
           !$OMP END ORDERED
           V1 = (Ve * dx * dy * dz * 0.529177d0) - Vnuc
           rr = (x1-xmid)**2 + (y1-ymid)**2 + (z1-zmid)**2
           r = dsqrt (rr)
           zef1(k) = V1 * r            
          endif
       enddo
    enddo
  enddo
  !$OMP END PARALLEL DO
4

3 に答える 3

2

rho1配列とrho2プライベートが宣言されているかのように見えます。この結果の 1 つは、各スレッドが並列領域に入るときに、これらの配列のプライベート インスタンスを持つことです。配列が大きい場合、プログラムは単に利用可能なメモリよりも多くのメモリを割り当てようとしている可能性があります。

共有されていない大規模な配列で OpenMP プログラムを作成することは比較的まれです。大規模な共有配列の異なる部分で動作する複数のスレッドは、おそらく OpenMP の正規のアプリケーションです。

于 2013-11-03T16:08:27.537 に答える
1

Web サイトの他の投稿「この openmp コードでセグメンテーション違反が発生する理由」から解決策を見つけました。この問題は、スタック サイズの制限によるものでした。次のコマンドで解決しました: ulimit -s unlimited

于 2013-11-06T06:18:01.510 に答える
1

1 つの問題として、変数がプライベートに宣言されている場合、各スレッドがオブジェクトのユニット化されたプライベート レプリカを作成することも考えられます。プライベート変数が並列化領域の前に変数の値を持つように、copyin openmp ステートメントを含める必要がある場合があります。

于 2014-06-06T17:11:07.820 に答える