我正在编写一些代码来激活CUDA上的神经网络,并且我遇到了一个问题。我没有得到进入给定神经元的权重的正确总和。对有多个线程写入相同索引的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
包含该信息。因此,sourceTargetArray
的索引i
是连接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存储器防护功能
在上面的示例代码中,'cache [cacheIndex] + 1'应该是'cache [cacheIndex + 1]'。 – 2016-11-25 06:14:22