2017-06-02 10 views
0

コードを並列化しようとしましたが、パフォーマンスが低下するだけでした。私はいくつかのモンテカルロ統合を実行し、その平均を見つけるFortranコードを書いた。OpenMPを使用して並列化する際のパフォーマンスの問題

 implicit none 
     integer, parameter :: n=100 
     integer, parameter :: m=1000000 
     real, parameter :: pi=3.141592654 

     real MC,integ,x,y 
     integer tid,OMP_GET_THREAD_NUM,i,j,init,inside 
     read*,init 
     call OMP_SET_NUM_THREADS(init) 
     call random_seed() 
!$OMP PARALLEL DO PRIVATE(J,X,Y,INSIDE,MC) 
!$OMP& REDUCTION(+:INTEG) 
     do i=1,n 
     inside=0 
     do j=1,m 
      call random_number(x) 
      call random_number(y) 

      x=x*pi 
      y=y*2.0 

      if(y.le.x*sin(x))then 
      inside=inside+1 
      endif 

     enddo 

     MC=inside*2*pi/m 
     integ=integ+MC/n 
     enddo 
!$OMP END PARALLEL DO 

     print*, integ 
     end 

スレッドの数を増やすと、実行時間が大幅に増加します。私はそのような問題の解決策を探していましたが、ほとんどの場合共有メモリ要素が問題になりましたが、私のケースにどのように影響しているのか分かりません。

私は、インテルFortranコンパイラを使用して16コア・プロセッサで実行しています。

EDIT:あなたは並列スレッドではない間違いなくハイパフォーマンス・コンピューティングのためのRANDOM_NUMBERを使用してはいけませんprivate節

+1

ようこそ。 [ツアー]を取ってください、それはすべての新規の方にお勧めです。どのように時間を測定しましたか? –

+0

コード内のインデントをどのように変更したかをご覧ください。人々が構造を見ることができるように、すべてのコードをインデントしておくとよいでしょう。ソースファイルをそのまま維持することは良いことです。 –

+0

「内部」とは何ですか?それはどこから来たのですか? 'IMPLICIT NONE'を必ず使用してください。 –

答えて

0

を、implicit noneを追加するすべての変数を宣言すると、追加した後のプログラム。乱数ジェネレータの品質と、標準乱数ジェネレータのスレッド安全性についての保証はありません。 Can Random Number Generator of Fortran 90 be trusted for Monte Carlo Integration?

一部のコンパイラは、並列に呼び出すことのできない高速アルゴリズムを使用します。いくつかのコンパイラは、メソッドを遅くするが、並列から呼び出すことができます。いくつかは速くて平行にすることができます。いくつかは、品質の悪いランダムシーケンスを生成します。

いくつかの並列PRNGライブラリを使用する必要があります。沢山あります。インテルの推奨事項はこちらhttps://software.intel.com/en-us/forums/intel-math-kernel-library/topic/283349http://www.cmiss.org/openCMISS/wiki/RandomNumberGenerationWithOpenMPのライブラリを少し改良したhttps://bitbucket.org/LadaF/elmm/src/e732cb9bee3352877d09ae7f6b6722157a819f2c/src/simplevtk.f90?at=master&fileviewer=file-view-defaultで使用していますが、アプリケーションのシーケンスの品質は気にしません。古いバージョンへ


あなたはそこに競合状態を持っています。

inside=inside+1 

以上のスレッドで

は書き込みのために競合すると、変数を読み込むことができます。何とかアクセスを同期させる必要があります。あなたはそれをプライベートにする場合は、あなたがそれを作る場合reductionあなたは

integ=integ+MC/n 

に問題があるでしょう、そしてinside=inside+1はローカルでのみカウントされます。

MCも競合状態にあるように見えます。これは、より多くのスレッドが書き込みを行うためです。 MCが何をしているのかはっきりしていません。理由はどこにでも値を使用していないためです。 あなたが表示したコードは完全ですか?そうでない場合は、Minimal, Complete, and Verifiable exampleを作成する方法を参照してください。

これを参照してくださいWith OpenMP parallelized nested loops run slow競合状態がどのようにプログラムを遅くすることができる多くの他の例を参照してください。

+0

に格納された' inside *(2 * pi)/ m'であり、デフォルトでは、私的な変数です。私は内側のループが別々のスレッドで独立して実行されるように、外側のループを並列に実行することを望みます。 「MC」は統合の価値を格納する。 'MC 'は独立してn回計算され、平均は' integ'に格納されます。私は 'integ'を削除しようとしていたので、時間差を見るだけですべてがプライベートになっていましたが、実行時間には何の影響もありませんでした。 –

+0

なぜプライベートでデフォルトになっていると思いますか?あなたのコードにそのような設定はありません。デフォルトではすべてが共有されます。私は、競争状態のためにプログラムが遅いと強く信じています。シリアルコードとパラレルコードの結果を比較しましたか?彼らは同じですか、あるいは違いますか?私は彼らが違うと思う。 –

+0

'DEFAULT(PRIVATE)'を追加しようとしましたが効果がありませんでした。そのため、デフォルトではプライベートでなければならないと思いました。意外なことに、結果は、 'DEFAULT(PRIVATE)'を使用して使用しても使用しなくても、直列コードと並列コードの両方で同じです。また、結果は小数点以下3桁まで正確です。私は 'PRIVATE'節を使って全ての変数をprivateに定義しようとしましたが、それは助けにもなりませんでした。 –

関連する問題