質問

乱数を非常に迅速に計算し、複数のスレッドに適用できるものを書き込もうとしています。私の現在のコードは次のとおりです。

/* Approximating PI using a Monte-Carlo method. */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <omp.h>
#define N 1000000000  /* As lareg as possible for increased accuracy */

double random_function(void);

int main(void)
{
   int i = 0;
    double X, Y;
   double count_inside_temp = 0.0, count_inside = 0.0;
   unsigned int th_id = omp_get_thread_num();
   #pragma omp parallel private(i, X, Y) firstprivate(count_inside_temp)
   {
      srand(th_id);
      #pragma omp for schedule(static)
      for (i = 0; i <= N; i++) {
         X = 2.0 * random_function() - 1.0;
         Y = 2.0 * random_function() - 1.0;
         if ((X * X) + (Y * Y) < 1.0) {
        count_inside_temp += 1.0;
     }
  }
  #pragma omp atomic
      count_inside += count_inside_temp;
   }
   printf("Approximation to PI is = %.10lf\n", (count_inside * 4.0)/ N);
   return 0;
}

double random_function(void)
{
   return ((double) rand() / (double) RAND_MAX);
}

これは機能しますが、リソースマネージャーを観察することから、すべてのスレッドを使用していないことを知っています。 rand()はマルチスレッドコードで機能しますか?そうでない場合は、良い選択肢がありますか?どうもありがとう。ジャック

役に立ちましたか?

解決

rand() 糸は安全ですか?多分そうでないかもしれません:

rand()関数は再入力する必要はありません。リエントラントである必要がない関数は、スレッドセーフである必要はありません。」

1つのテストと優れた学習演習は、コールを交換することです rand() たとえば、固定整数で、何が起こるかを確認します。

擬似ランダム数ジェネレーターについて私が考える方法は、整数を入力としてとり、整数を出力として返すブラックボックスとしてです。特定の入力の場合、出力は常に同じですが、数値のシーケンスにパターンはなく、シーケンスは可能な出力の範囲に均一に分布しています。 (このモデルは完全に正確ではありませんが、実行します。)このブラックボックスを使用する方法は、凝視番号(シード)を選択することです。乱数ジェネレーター。 APIを設計するには、2つの一般的なアプローチがあります。

  1. 2つの機能、1つは初期シードを設定します(例: srand(seed))そして、シーケンスから次の値を取得する1つ(例: rand())。 PRNGの状態は、一種のグローバル変数に内部に保存されます。新しい乱数を生成することは、スレッドセーフではありません(伝えにくいですが、出力ストリームは再現性がありません)、または多額のコードでは遅くなります(状態値に関するいくつかのシリアル化が行われます)。
  2. PRNG状態がアプリケーションプログラマにさらされるインターフェイス。ここでは、通常、3つの機能があります。 init_prng(seed), 、PRNG状態の不透明な表現を返します。 get_prng(state), 、乱数を返し、状態変数を変更し、 destroy_peng(state), 、割り当てられたメモリなどをクリーンアップするだけです。このタイプのAPIを使用したPRNGはすべてスレッド安全で、ロックなしで並行して実行する必要があります((現在のスレッドローカル)状態変数の管理を担当しているためです。

私は通常、Fortranで書き、使用します ラッドの Mersenne Twister Prngの実装(そのリンクは読む価値があります)。 Cには、状態を管理にさらしている適切なPRNGがたくさんあります。 prng 見栄えが良く、これを使用して(初期化と並列領域および民間の状態変数内のコールを破壊する)、まともなスピードアップが得られるはずです。

最後に、多くの場合、PRNGは、一度に一連の乱数を要求する場合にパフォーマンスを向上させることができます(たとえば、コンパイラはPRNG内部をベクトル化できます)。このため、このライブラリはしばしばそのようなものを持っています get_prng_array(state) まるであなたが置くかのように、乱数でいっぱいの配列を返す機能 get_prng 配列要素を埋めるループで - 彼らはそれをより迅速に行います。これは2番目の最適化になります(ループのパラレル内にループに追加される必要があります。明らかに、これを行うスレッドごとのスタックスペースを使い果たしたくありません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top