2016-09-06 20 views
1

私はn個のボディシミュレーションを行い、パーティクルの加速を格納する配列を持っています。今ではコードを並列化しようとしていますが、配列が実数型なのでこの問題は発生しました。ロックできません。 OpenMPのinit_lockサブルーチンのため、引数は整数でなければなりません。OpenMPを使用してロック配列インデックスを使用するには?

方法はありますか?私はクリティカルなコンストラクトを使用しましたが、計算時間には影響しません。ここでは、配列のインデックスをロックしようとしましたが、どちらも動作していません。

call omp_init_lock(i,j) 

    !$omp parallel 
    !$omp do private(rx,ry,rz,rsqd,r2i,r6i,virij,ff,i,j) schedule(dynamic) 
    do i=1,m-1 
     do j=i+1,m 
      rsqd = 0.0 
       rx = x(i,1) - x(j,1) 
       ry = x(i,2) - x(j,2) 
       rz = x(i,3) - x(j,3)          
       rsqd = rsqd + rx*rx +ry*ry + rz*rz 
       !calculation of another variable ff 
       ! $omp critical 
       call omp_set_lock(i) 
        a(i,1) = a(i,1) + rx*ff 
        a(i,2) = a(i,2) + ry*ff 
        a(i,3) = a(i,3) + rz*ff 
       call omp_unset_lock(i) 
       call omp_set_lock(j)          
        a(j,1) = a(j,1) - rx*ff 
        a(j,2) = a(j,2) - ry*ff 
        a(j,3) = a(j,3) - rz*ff 
       call omp_unset_lock(j) 
       ! $omp end critical   
     end do 
    end do 
+1

Bcz、U、Plsはここに似たような言語を使用しないでください。それはクールではない。 –

+0

"!$ OMP"間のスペースは受け入れられますか? – Holmz

+0

@Holmz、いいえ、スペースは使用できません。 OpenMP仕様では、スペースが無視される固定フォーマットのFortranについても、センチネルが文字を介さずに単一の単語として表示される必要があることは明らかです。 –

答えて

0

あなたが見つけたロックが定義されたコード内のコードを実行するスレッドを1つだけ許可するデータ構造です:

は、だから私はあなたのような何かをすることをお勧めしたいです。マトリックスの各セルへのアクセスを保護したい場合は、マトリックス全体に対して1つのロックをかけるか、各セルを保護するか、行/列ごとのアクセスを保護するなどの方法で保護します。

私はあなたが持っている重要な課題のそれぞれにomp atomic構造を使用することをお勧めします。 omp criticalおよびロックとは対照的に、アトミックの利点は、アトミックプロセッサ命令によってコンパイラ/ランタイムによってアトミックをインプリメントできるため、単一プロセッサによって実行される命令の量が削減されるためパフォーマンスが向上することです(openMP, atomic vs critical?およびhttp://openmp.org/forum/viewtopic.php?f=3&t=1549参照)。 omp atomicの構造を使用するもう1つの利点は、コンパイル時にOpenMPコードが有効になっていないときにコードが無意識にコンパイルされることです。ロックを使用する場合はそうではありません。

これはあなたのコードのバリエーションが考えられます。あなたは私はあなたがそのようなインテル®VTune [として(一部のパフォーマンス解析ツールを使用することをお勧めしたい本からさらにパフォーマンスを得ることに興味を持っているので

!$omp parallel 
!$omp do private(rx,ry,rz,rsqd,r2i,r6i,virij,ff,i,j) schedule(dynamic) 
do i=1,m-1 
    do j=i+1,m 
     rsqd = 0.0 
      rx = x(i,1) - x(j,1) 
      ry = x(i,2) - x(j,2) 
      rz = x(i,3) - x(j,3)          
      rsqd = rsqd + rx*rx +ry*ry + rz*rz 
      !calculation of another variable ff 
      !$omp atomic 
      a(i,1) = a(i,1) + rx*ff 
      !$omp atomic 
      a(i,2) = a(i,2) + ry*ff 
      !$omp atomic 
      a(i,3) = a(i,3) + rz*ff 
      !$omp atomic 
      a(j,1) = a(j,1) - rx*ff 
      !$omp atomic 
      a(j,2) = a(j,2) - ry*ff 
      !$omp atomic 
      a(j,3) = a(j,3) - rz*ff 
    end do 
end do 

EDIT 1]、Paraver [2]、TAU [3]、Scalasca [4]、さらにはgprof)である。言い換えれば、このコードを並列化するときに言及した小さな影響は、このループが実行実行時間のわずかな部分を占めることを示している可能性があります。パフォーマンス分析ツールは、最も時間のかかるルーチンであることを特定するのに役立ちます。

このコード部分が代表的なものである場合、並列領域を作成してそれを待つか、クリティカル/アトミック領域のためにシリアライズするコストが、スピードアップを制限する可能性があります。まず、dynamicスケジューリングに最小チャンク(例:dynamic, 4)を提供することを検討してください。これは、imに近く、従ってdo jループが膨大な量の作業を表していない最後の反復に役立ちます。 guidedスケジューリングを検討することもできます。その動作はdynamicと何らかの形で似ていますが、反復回数(チャンク)は動的に減少します。

[1] https://software.intel.com/en-us/intel-vtune-amplifier-xe

[2] http://www.bsc.es/computer-sciences/performance-tools/paraver

[3] http://www.cs.uoregon.edu/research/tau/home.php

[4] http://www.scalasca.org

+0

'@ Harald'' atomic'構造体を使うと 'critical'構造体よりも優れたパフォーマンスが得られますが、どちらの場合も私のシリアルプログラムは2つよりも速いです。この可能性のある理由は何でしょうか? – user1844

+0

複数の要因に依存するWRTパフォーマンス。私はそれをカバーしようとする私の答えを更新しようとします。 – Harald

+0

'@ Harald'ありがとうございました。パフォーマンスが向上しました。コード内のすべての2D配列を複数の1D配列(つまり、a(i、j)からax(i)、ay(i)、およびaz(i)に変更しました。 ) ')。今は私のパラレルコードがシリアルより高速に実行されています。しかし、理由はわかりません。 – user1844

0

つのオプションは、(彼らは重複して使用されている)a(i,x)a(j,x)文の周りに1つのクリティカルセクションを使用し、すべてのロックを排除することです。

!$omp parallel 
!$omp do private(rx,ry,rz,rsqd,r2i,r6i,virij,ff,i,j) schedule(dynamic) 
do i=1,m-1 
    do j=i+1,m 
     rsqd = 0.0 
      rx = x(i,1) - x(j,1) 
      ry = x(i,2) - x(j,2) 
      rz = x(i,3) - x(j,3)          
      rsqd = rsqd + rx*rx +ry*ry + rz*rz 
      !calculation of another variable ff 
      ! $omp critical     
       a(i,1) = a(i,1) + rx*ff 
       a(i,2) = a(i,2) + ry*ff 
       a(i,3) = a(i,3) + rz*ff 
       a(j,1) = a(j,1) - rx*ff 
       a(j,2) = a(j,2) - ry*ff 
       a(j,3) = a(j,3) - rz*ff 
      ! $omp end critical   
    end do 
end do 
+0

あなたのアプローチは有効ではないと思います。あなたはまだ競争条件があります。たとえば、 'a(3,1)'の値は 'i = 3'や' j = 3'の2つの異なるスレッドで書かれ、保護が必要です。 – Harald

+0

ああ、そうだよ。それを逃した。その場合、クリティカルセクションは 'a(i、x)'ステートメントの前に開始する必要があります。ありがとう – user3630220

+0

おそらくあなたの答えを編集して更新したいと思うでしょう。 – Harald

関連する問題