3

CURAND ライブラリを使用して、0 から 100 までの互いに完全に独立した乱数を生成しようとしています。したがって、各スレッドにシードとして時間を与え、「id = threadIdx.x + blockDim.x * blockIdx.x」を指定しています。 "シーケンスおよびオフセットとして。次に、乱数を float として取得した後、100 を掛けて整数値を取得します。

今、私が直面している問題は、11 であるコードを何回実行しても、スレッド [0,0] と [0,1] に対して同じ乱数を取得することです。私は間違っています。助けてください。

以下にコードを貼り付けます。

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include<curand_kernel.h>
#include "util/cuPrintf.cu"
#include<time.h>

#define NE WA*HA //Total number of random numbers 
#define WA 2   // Matrix A width
#define HA 2   // Matrix A height
#define SAMPLE 100 //Sample number
#define BLOCK_SIZE 2 //Block size

__global__ void setup_kernel ( curandState * state, unsigned long seed )
{
int id = threadIdx.x  + blockIdx.x + blockDim.x;
curand_init ( seed, id , id, &state[id] );
}

__global__ void generate( curandState* globalState, float* randomMatrix )
{
int ind = threadIdx.x + blockIdx.x * blockDim.x;
if(ind < NE){
    curandState localState = globalState[ind];
    float stopId = curand_uniform(&localState) * SAMPLE;
    cuPrintf("Float random value is : %f",stopId);
    int stop = stopId ;
    cuPrintf("Random number %d\n",stop);
    for(int i = 0; i < SAMPLE; i++){
            if(i == stop){
                    float random = curand_normal( &localState );
                    cuPrintf("Random Value %f\t",random);
                    randomMatrix[ind] = random;
                    break;
            }
    }
    globalState[ind] = localState;
}
}

/////////////////////////////////////////////////////////
// Program main
/////////////////////////////////////////////////////////

int main(int argc, char** argv)
{

// 1. allocate host memory for matrix A
unsigned int size_A = WA * HA;
unsigned int mem_size_A = sizeof(float) * size_A;
float* h_A = (float* ) malloc(mem_size_A);
time_t t;

// 2. allocate device memory
float* d_A;
cudaMalloc((void**) &d_A, mem_size_A);

// 3. create random states    
curandState* devStates;
cudaMalloc ( &devStates, size_A*sizeof( curandState ) );

// 4. setup seeds
int n_blocks = size_A/BLOCK_SIZE;
time(&t);
printf("\nTime is : %u\n",(unsigned long) t);
setup_kernel <<< n_blocks, BLOCK_SIZE >>> ( devStates, (unsigned long) t );
// 4. generate random numbers
cudaPrintfInit();
generate <<< n_blocks, BLOCK_SIZE >>> ( devStates,d_A );
cudaPrintfDisplay(stdout, true);
cudaPrintfEnd();
// 5. copy result from device to host
cudaMemcpy(h_A, d_A, mem_size_A, cudaMemcpyDeviceToHost);


// 6. print out the results
printf("\n\nMatrix A (Results)\n");
for(int i = 0; i < size_A; i++)
{
   printf("%f ", h_A[i]);
   if(((i + 1) % WA) == 0)
      printf("\n");
}
printf("\n");

// 7. clean up memory
free(h_A);
cudaFree(d_A);

}

私が得る出力は次のとおりです。

時間: 1347857063 [0, 0]: 浮動小数点乱数値: 11.675105[0, 0]: 乱数 11 [0, 0]: 乱数値 0.358356 [0, 1]: 浮動小数点乱数値: 11.675105[0, 1 ]: 乱数 11 [0, 1]: 乱数値 0.358356 [1, 0]: 浮動小数点の乱数値: 63.840496[1, 0]: 乱数値 63 [1, 0]: 乱数値 0.696459 [1, 1]:浮動小数点のランダム値: 44.712799[1, 1]: 乱数 44 [1, 1]: ランダム値 0.735049

4

1 に答える 1

4

ここにはいくつか問題があります。ここで最初の問題に対処して、作業を開始してください。

一般的なポイント

  • すべての CUDA API 呼び出しの戻り値を確認してください。詳細については、こちらを参照してください。
  • cuda-memcheck を実行して、範囲外のアクセスなどの明らかなものを確認してください。

具体的なポイント

  • RNG 状態にスペースを割り当てるときは、スレッドごとに 1 つの状態用のスペースが必要です (現在のように行列要素ごとに 1 つではありません)。
  • setup_kernel() でのスレッド ID の計算が間違っていますthreadIdx.x + blockIdx.x * blockDim.x。(+ ではなく *) にする必要があります。
  • スレッド ID をオフセットと同様にシーケンス番号として使用します。cuRAND マニュアルで説明されているように、オフセットをゼロに設定する必要があります。

最高品質の並列疑似乱数を生成するには、各実験に一意のシードを割り当てる必要があります。実験内では、計算の各スレッドに一意のシーケンス番号を割り当てる必要があります。

最後に、ブロックごとに 2 つのスレッドを実行していますが、これは非常に非効率的です。詳細については、CUDA C プログラミング ガイドの「使用率の最大化」セクションを参照してください。ただし、ブロックごとに 32 の倍数のスレッド (たとえば、128、256) と多数のブロック (たとえば、数万) を起動することを検討する必要があります。 )。問題が小さい場合は、一度に複数の問題を実行することを検討してください (単一のカーネル起動でバッチ処理するか、同時実行を得るために異なるストリームのカーネルとして)。

于 2012-09-17T09:01:28.310 に答える