私はCUDAの助けを借りて65536要素の配列を減らしようとしています(その中の要素の合計を計算します)。カーネルは次のようになります(今のところ* dev_distanceFloatsとインデックス引数は無視してください)
__global__ void kernel_calcSum(float *d, float *dev_distanceFloats, int index) {
int tid = threadIdx.x;
float mySum = 0;
for (int e = 0; e < 256; e++) {
mySum += d[tid + e];
}
}
antそれは256スレッドの1つのブロックとして起動しました:
kernel_calcSum <<<1, 256 >>>(dev_spFloats1, dev_distanceFloats, index);
これまでのところ、256個のスレッドのそれぞれがグローバルメモリから256個の要素を取得し、ローカル変数mySumでその合計を計算します。カーネルの実行時間は約45ミリ秒です。次のステップは、ブロック内の256スレッド間に共有メモリを導入することです(mySumの合計を計算するため)。したがって、カーネルは次のようになります。
__global__ void kernel_calcSum(float *d, float *dev_distanceFloats, int index) {
__shared__ float sdata[256];
int tid = threadIdx.x;
float mySum = 0;
for (int e = 0; e < 256; e++) {
mySum += d[tid + e];
}
sdata[tid] = mySum;
}
共有メモリへの書き込みを追加しましたが、実行時間が45ミリ秒から258ミリ秒に増加します(NVidia Visual Profiler 5.0.0を使用してこれをチェックしています)。sdata変数に書き込むときに、スレッドごとに8つのバンク競合があることに気付きました(32バンクの機能3.0を持つGTX670を使用しています)。実験として、カーネルを起動するときにスレッドを32に減らしようとしましたが、それでも時間は258ミリ秒です。
質問1:私の場合、共有メモリへの書き込みに時間がかかるのはなぜですか?質問2:「実行計画」(メモリアクセス、競合などのタイミング)を詳細に示すツールはありますか?
あなたの提案をありがとう。
更新: カーネルで遊んでいます-スレッドごとにsdataを定数に設定しました:
__global__ void kernel_calcSum(float *d, float *dev_distanceFloats, int index) {
__shared__ float sdata[256];
int tid = threadIdx.x;
float mySum = 0;
for (int e = 0; e < 256; e++) {
mySum += d[tid + e];
}
sdata[tid] = 111;
}
タイミングは48ミリ秒に戻ります。したがって、sdata [tid]=mySum;を変更します。to sdata [tid] = 111; これを作りました。
このコンパイラの最適化(この行を削除しただけでしょうか?)または何らかの理由でローカルメモリ(レジスタ?)から共有へのコピーに時間がかかりますか?