今日、友人と話をしたところ、GPU を使用してモンテカルロ シミュレーションを作成しようとしているとのことでした。興味深いことに、彼は、異なるプロセッサでランダムに数字を描きたいと言い、無相関であると仮定しました。しかし、そうではありませんでした。
問題は、複数の GPU で独立した数値セットを描画する方法が存在するかどうかです。彼は、それぞれに異なる種をとれば問題は解決すると考えましたが、そうではありませんでした。
説明が必要な場合はお知らせください。詳細を提供するように依頼します。
今日、友人と話をしたところ、GPU を使用してモンテカルロ シミュレーションを作成しようとしているとのことでした。興味深いことに、彼は、異なるプロセッサでランダムに数字を描きたいと言い、無相関であると仮定しました。しかし、そうではありませんでした。
問題は、複数の GPU で独立した数値セットを描画する方法が存在するかどうかです。彼は、それぞれに異なる種をとれば問題は解決すると考えましたが、そうではありませんでした。
説明が必要な場合はお知らせください。詳細を提供するように依頼します。
完全に独立した乱数を生成するには、並列乱数ジェネレーターを使用する必要があります。基本的に、単一のシードを選択すると、M個の独立した乱数ストリームが生成されます。したがって、M個のGPU のそれぞれで、独立したストリームから乱数を生成できます。
複数の GPU を扱うときは、次のことが必要であることに注意する必要があります。
各 GPU コアで乱数を生成するのは難しいことがわかりました (私がしばらく前に尋ねたこの質問を参照してください)。私が GPU と RN をいじっていたとき、一度に大量の数値を生成した場合にのみ、GPU でのランダム生成のスピードアップが得られました。
代わりに、次の理由から、CPU で乱数を生成します。
コメントであなたの質問に答えるには: 乱数は何に依存していますか?
非常に基本的な乱数ジェネレーターは、線形合同ジェネレーターです。このジェネレーターは新しい方法に追い越されていますが、それらがどのように機能するかについてのアイデアが得られるはずです。基本的に、i 番目の乱数は (i-1) の乱数に依存します。ご指摘のとおり、2 つのストリームを十分長く実行すると、それらはオーバーラップします。大きな問題は、それらがいつ重なるかわからないことです。
iidユニフォーム変数を生成するには、ジェネレーターを異なるシードで初期化するだけです。Cuda では、Mersenne Twister ジェネレーターを実装する NVIDIA Curand Library を使用できます。
たとえば、100 個のカーネルで並列に実行される次のコードは、(R^10)-uniform の 10 個のサンプルを描画します。
__global__ void setup_kernel(curandState *state,int pseed)
{
int id = blockIdx.x * blockDim.x + threadIdx.x;
int seed = id%10+pseed;
/* 10 differents seed for uncorrelated rv,
a different sequence number, no offset */
curand_init(seed, id, 0, &state[id]);
}
「良い」ジェネレーター (Mersenne Twister など) を使用すると、異なるランダム シードを持つ 2 つのシーケンスは、GPU であれ CPU であれ、無相関になります。したがって、異なる GPU で異なるシードを取得するだけでは十分ではないと言っている意味がわかりません。詳しく教えてください。