2

CURAND ライブラリを使用して、CUDA でランダム生成コードを作成しています。乱数生成について読んだことで、同じシードを使用すると同じ乱数のセットが得られると信じるようになりました。しかし、私がテストしたときはそうではありませんでした。私が間違っていることを説明してください。参照用に以下のコードを貼り付けます。


    curandGenerator_t rand_gen;  
    status = curandCreateGenerator (&rand_gen ,CURAND_RNG_PSEUDO_DEFAULT );  
    if(status != CURAND_STATUS_SUCCESS){  
            printf("Error encountered in generating handle\n");  
    }  
    status = curandSetPseudoRandomGeneratorSeed (rand_gen ,1234ULL);  
    if(status != CURAND_STATUS_SUCCESS){  
            printf("Error encountered in setting seed\n");  
    }  

    for(j=0; j<2; j++){  
            status = curandGenerate(rand_gen,a_d,N);  
            if(status != CURAND_STATUS_SUCCESS){  
                    printf("Error encountered in generating random numbers\n");  
             }

            cudaMemcpy ( a_h , a_d , N * sizeof(unsigned int),cudaMemcpyDeviceToHost);  
            for(i = 0; i < N; i++){  
                    printf("%d : %u\n",i,a_h[i]);  
            }
            printf("-----------%d----------------------\n",j);  
    }  
    status = curandDestroyGenerator(rand_gen);  
    if(status != CURAND_STATUS_SUCCESS){  
            printf("Error encountered in destroying handle\n");  
    }  

出力:

0:624778773
1:3522650202
2:2363946744
3:1266286439
4:3928747533
5:37322235839
6:1382638835
7:3362343509
8:48542993
9:122599299299299299299299299299299299299299299299299299299299299299299299299299299299299208
--- -------------
0:3356973615
1:1004333919
2:2916556602
3:1213079917
4:2705410958
5:520650207
6:1860816870
7:1645310928
8:22057551999 :
12829999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
---1----------------------

4

2 に答える 2

5

疑似乱数発生器の「状態」の概念があります。たとえば、Mersenne twister の状態のサイズは約 1024 語ですが、デフォルトの XORWOW の状態のサイズはわずか数語です (ただし、期間もはるかに短くなります)。

「setPseudoRandomGeneratorSeed」を呼び出すたびに、ジェネレーターの状態を初期化します。その後、curandGenerate を呼び出すと、この状態が更新され (つまり、ある乱数から次の乱数に移動するには、状態を再計算する必要があります)、ランダム シーケンスのさまざまな部分が生成されます。

また、ドライバー API を試してみることもできます。ここでは、curandInit() が各スレッドの状態を初期化しますが、これは非常にコストがかかる可能性があります。その後、curand() または curandUniform() などへのその後の呼び出しは、この状態を再利用します。実際、各スレッドはランダム シーケンスの異なるオフセットから開始します。

于 2012-08-31T20:17:18.870 に答える