Некоторые выходные значения устанавливаются на 1, некоторые нет.Проблема заключается в следующем:
// Calculate Global index (Generic 3D block, 3D thread)
long idx = ( blockIdx.x + blockIdx.y * gridDim.x * gridDim.y * blockIdx.z )
* ( threadIdx.z * ( blockDim.x*blockDim.y ) ) + threadIdx.y
* blockDim.x + threadIdx.x;
Это не то, что я бы назвал правильным общим преобразованием трехмерной сетки / блока в глобально уникальный одномерный индекс, который, как я полагаю, является вашим намерением.Давайте просто выберем один пример, чтобы доказать, что он сломан.Предположим, вы запускаете 1D сетку из 1D блоков (что вы и делаете).Тогда все переменные (block, thread) Idx.y и .z будут равны нулю.Только blockIdx.x и threadIdx.x могут принимать ненулевые значения в этой конфигурации запуска.
В этом случае ваше выражение уменьшается до:
// Calculate Global index (Generic 3D block, 3D thread)
long idx = ( blockIdx.x + 0 * gridDim.x * gridDim.y * 0 )
* ( 0 * ( blockDim.x*blockDim.y ) ) + 0
* blockDim.x + threadIdx.x;
, то есть оно уменьшается до:
long idx = threadIdx.x;
Итак, первые (размером с блок) элементы ваших массивов (a, b, c, d) установлены правильно, остальные - нет.Поскольку threadIdx.x
не является уникальным от одного блока к другому, это не правильный глобально уникальный идентификатор потока, и поэтому каждый блок записывает одинаковые выходные местоположения, а не каждый заботится о отдельномчасть массива.
Итак, что такое возможное (правильное) общее преобразование индекса 3D-в-1D?
Ответ здесь (и, вероятно, в других местах),Этот ответ фактически преобразует только конфигурацию трехмерной сетки плюс одномерного блока в глобально уникальный идентификатор, но этого достаточно для демонстрации того, что не так в этом коде.
Когда я заменяю ваши вычисления в ядре idx
с этим кодом ваше ядро заполняет все записи массива 1.0 согласно моему тестированию.