CUDAでニューラルネットワークをアクティブ化するためのコードを書いていますが、問題が発生しています。特定のニューロンに入る重みの正しい合計が得られません。
これがカーネルコードです。変数を使ってもう少しわかりやすく説明します。
__global__ void kernelSumWeights(float* sumArray, float* weightArray, int2* sourceTargetArray, int cLength)
{
int nx = threadIdx.x + TILE_WIDTH*threadIdx.y;
int index_in = (blockIdx.x + gridDim.x*blockIdx.y)*TILE_WIDTH*TILE_WIDTH + nx;
if(index_in < cLength)
{
sumArray[sourceTargetArray[index_in].y] += fabs(weightArray[index_in]);
//__threadfence();
__threadfence_block();
}
}
まず、ネットワーク内の接続数はですcLength。すべての接続には、ソースニューロンとターゲットニューロン、およびその接続の重みがあります。SourceTargetArrayその情報が含まれています。したがって、のインデックスiはsourceTargetArray接続のソースニューロンインデックスであり、接続iのターゲットニューロンインデックスですi。にはweightArray重み情報が含まれています(したがって、のインデックスiはweightArray接続に対応しますi)。
ご覧のとおり、SumArrayここに合計を保存しています。したがって、カーネルはsumArray(接続のターゲットニューロンインデックスでi)接続の重みの絶対値だけ増分しますi。直感的には、ニューロンへのすべての着信接続について、すべての重みを合計します。私がこのカーネルでやろうとしているのはこれだけです。最終的には、この合計を使用して重みを正規化します。
問題はそれが間違っているということです。私はこれを連続して行いましたが、答えは異なります。答えは異なり、通常は約12〜15倍です(したがって、正しい答えは700.0になり、私が得ているのは50年代の範囲です)。
私が追加したことがわかります__threadfence()(そして__threadfence_block()、書き込みがすべてのスレッドによって同時に行われていないことを確認するために)。これが私のコードの問題かどうかはわかりません。ウェイト配列がテストしたシリアルバージョンと同一であり、ソース/ターゲット情報も同一であることを確認しました。私は何が間違っているのですか?
編集:参考までに、__threadfence()usagedはCUDAプログラミングガイドv3.1付録B.5メモリフェンス機能で説明されています