Я пишу код для активации нейронных сетей в 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()
используется описано в Руководстве по программированию CUDA v3.1, Приложение B.5 Функции забора памяти