9

私はここに来たばかりで、C の初心者レベルのプログラマーです。openmp を使用して for ループを高速化するのに問題があります。以下は簡単な例です。

#include <stdlib.h>
#include <stdio.h>
#include <gsl/gsl_rng.h>
#include <omp.h>

gsl_rng *rng;

main()
{
int i, M=100000000;
double tmp;

/* initialize RNG */
gsl_rng_env_setup();
rng = gsl_rng_alloc (gsl_rng_taus);
gsl_rng_set (rng,(unsigned long int)791526599);

// option 1: parallel        
  #pragma omp parallel for default(shared) private( i, tmp ) schedule(dynamic)
  for(i=0;i<=M-1;i++){
     tmp=gsl_ran_gamma_mt(rng, 4, 1./3 );
  }


// option 2: sequential       
  for(i=0;i<=M-1;i++){
     tmp=gsl_ran_gamma_mt(rng, 4, 1./3 );
  }
}

このコードは、M 反復のガンマ ランダム分布から抽出されます。openmp を使用した並列アプローチ (オプション 1) には約 1 分かかりますが、順次アプローチ (オプション 2) には 20 秒しかかかりません。openmp で実行している間、CPU 使用率が 800% であることを確認できます (使用しているサーバーには 8 つの CPU があります)。また、システムはGCC 4.1.3を搭載したLinuxです。私が使用しているコンパイルコマンドは gcc -fopenmp -lgsl -lgslcblas -lm (私は GSL を使用しています)

私は何か間違ったことをしていますか?私を助けてください!ありがとう!

PS一部のユーザーから指摘されたように、rngが原因である可能性があります。でも交換しても

tmp=gsl_ran_gamma_mt(rng, 4, 1./3 );

言うまでもなく

tmp=1000*10000;

問題はまだそこにあります...

4

3 に答える 3

12

gsl_ran_gamma_mtおそらく、並行性の問題を防ぐためにロックオンrngします(そうでない場合は、並列コードに競合状態が含まれている可能性があるため、誤った結果が生成されます)。rngその場合の解決策は、スレッドごとに個別のインスタンスを作成して、ロックを回避することです。

于 2012-08-23T15:58:54.697 に答える
5

変数rngは共有されているため、スレッドは乱数ジェネレーターを使用できるようになるまですべての時間を費やしています。各スレッドにRNGの個別のインスタンスを与えます。これはおそらく、RNG初期化コードも並行して実行することを意味します。

于 2012-08-23T15:58:57.407 に答える
1

助けてくれてありがとう。私はちょうど私が取り除く場合、それを知った

schedule(dynamic)

コードでは、問題は消えます。しかし、それはなぜですか?

于 2012-08-23T18:23:25.413 に答える