1

Fortran95とgfortranコンパイラを使用したコードがあります。私もOpenMPを使用しており、非常に大きな配列を処理する必要があります。私のコードでは、OpenBLASのソルバーDGTSVを使用して連立一次方程式を解く必要もあります。このソルバーも、それが可能なはずのopenblasを使用して並列化したいと思います。しかし、構文に問題があります。添付の擬似コードを使用すると、4つのCPUすべてがほぼ100%使用されますが、各カーネルが線形方程式を個別に解くのか、それとも部分に分割して並列に計算するのかはわかりません。全体はを使用してコンパイルされますgfortran -fopenmp -lblas a.f95 -o a.out

だから私の擬似コードは次のようになります

program a
implicit none
integer, parameter  ::  N   =       200
real*8, dimension(numx) ::  D   =       0.0
real*8, dimension(numx-1):: DL  =       0.0
real*8, dimension(numx-1):: DU  =       0.0
real*8, dimension(numx) ::  b   =       0.0
integer         ::  info    =       0
integer :: numthread=4
...
!$OMP PARALLEL NUM_THREADS(numthread)
...
!$OMP DO
...
!$OMP END DO
CALL DGTSV(N,1,DL,D,DU,b,N,info)
!$OMP DO
...
!$OMP END DO
...
!$OMP END PARALLEL
end program a

ソルバーを並列化して、各カーネルがソルバーの一部を計算するようにするには、何をする必要がありますか?

4

1 に答える 1

1

OpenMP 並列領域内では、すべてのスレッドが (MPI と同様に) 同じコードを実行し、スレッドがループ/セクション/タスクに到達したときにのみ作業が分割されます。

あなたの例では、ループ内の作業 ( OMP DO) は、使用可能なスレッド間で分散されます。ループが完了すると、暗黙的なバリアによってすべてのスレッドが同期され、関数が並列に実行されますDGTSV。サブルーチンが戻った後、ループは再び分割されます。

@HristoIlievは、OMP SINGLE句を使用して提案しました。これにより、内部のコードの一部が 1 つのスレッドのみによって実行されるように制限され、他のすべてのスレッドがそれを待機するように強制されます (指定しない限りnowait)。

一方、ネストされた並列処理は、別の並列領域内で並列領域を宣言する場合に呼び出されます。これは、並列領域内で OpenMP 並列化ライブラリへの呼び出しを実行する場合にも適用されます。

デフォルトでは、OpenMP はネストされた並列領域の並列処理を増やしません。代わりに、並列領域に入るスレッドのみがそれを実行できます。この動作は、環境変数OMP_NESTEDtoを使用して変更できますtrue

次のループでリソースが再利用されるため、このOMP SINGLEソリューションは並列領域を 2 つに分割するよりもはるかに優れています。

$!OMP PARALLEL
  $!OMP DO
  DO ...
  END DO

  $!OMP SINGLE
  CALL DGTSV(...)

  $!OMP DO
  DO ...
  END DO
$!OMP END PARALLEL

の使用法を説明するためOMP_NESTEDに、OpenMP を使用するように構成された FFTW (高速フーリエ変換の実装) を使用するアプリケーションから得た結果をいくつか示します。実行は、16 コア 2 ソケット Intel Xeon E5 @2.46GHz ノードで実行されました。

次のグラフは、アプリケーション全体で費やされた時間を示しています。CPU が 1 より大きい場合は並列領域、CPU が 1 の場合はシリアル化された領域、CPU が 0 の場合は同期領域が表示されます。

アプリケーションは恥ずかしいほど並列であるため、この特定のケースでは、ネストを使用する価値はありません (FFTW はそれほどスケーリングしません)。

これがOMP_NESTED=false実行です。外部並列領域 (ftdock) で費やされるスレッドの量によって、並列処理の量がどのように制限されるかを観察します。

ネストされていない OpenMP バージョン

これがOMP_NESTED=true実行です。この場合、外部並列領域で費やされるスレッドの量よりもさらに並列処理を増やすことができます。この場合に可能な最大並列処理は 16 です。8 つの外部スレッドが内部並列領域を実行する単一のピアを作成するか、4 つの外部スレッドがそれぞれ 3 つの追加スレッドを作成する場合 (8x2 = 4x4 = 16)。

ネストされた OpenMP バージョン

于 2016-10-06T15:29:57.523 に答える