これはパフォーマンス関連の質問です。「CUDA By Example」サンプルコードに基づいて、次の単純な CUDA カーネルを作成しました。
#define N 37426 /* the (arbitrary) number of hashes we want to calculate */
#define THREAD_COUNT 128
__device__ const unsigned char *m = "Goodbye, cruel world!";
__global__ void kernel_sha1(unsigned char *hval) {
sha1_ctx ctx[1];
unsigned int tid = threadIdx.x + blockIdx.x * blockDim.x;
while(tid < N) {
sha1_begin(ctx);
sha1_hash(m, 21UL, ctx);
sha1_end(hval+tid*SHA1_DIGEST_SIZE, ctx);
tid += blockDim.x * gridDim.x;
}
}
コードは私には正しいように見え、実際に同じハッシュの 37,426 個のコピーを吐き出します (予想どおりです。第 5 章のセクション 5.3 を読んだことに基づいて、「hval」として渡されたグローバル メモリに書き込む各スレッドは、非常に非効率になります。
次に、共有メモリを使用してパフォーマンスを向上させるキャッシュと思われるものを実装しました。コードは次のように変更されました。
#define N 37426 /* the (arbitrary) number of hashes we want to calculate */
#define THREAD_COUNT 128
__device__ const unsigned char *m = "Goodbye, cruel world!";
__global__ void kernel_sha1(unsigned char *hval) {
sha1_ctx ctx[1];
unsigned int tid = threadIdx.x + blockIdx.x * blockDim.x;
__shared__ unsigned char cache[THREAD_COUNT*SHA1_DIGEST_SIZE];
while(tid < N) {
sha1_begin(ctx);
sha1_hash(m, 21UL, ctx);
sha1_end(cache+threadIdx.x*SHA1_DIGEST_SIZE, ctx);
__syncthreads();
if( threadIdx.x == 0) {
memcpy(hval+tid*SHA1_DIGEST_SIZE, cache, sizeof(cache));
}
__syncthreads();
tid += blockDim.x * gridDim.x;
}
}
2 番目のバージョンも正しく動作しているように見えますが、最初のバージョンより数倍遅くなります。後者のコードは約 8.95 ミリ秒で完了し、前者は約 1.64 ミリ秒で実行されます。スタック オーバーフロー コミュニティへの私の質問は単純です。なぜですか?