Как рассчитать индексы координат отдельных нитей в трехмерных сетках?
У меня есть трехмерная сетка, состоящая из 3 D блоков. Я хочу рассчитывать индексы отдельных потоков каждой координаты каждый раз, когда вызывается ядро. У меня есть эти параметры:
dim3 blocks_query(32,32,32);
dim3 threads_query(32,32,32);
kernel<<< blocks_query,threads_query >>>();
Внутри ядра я хочу вычислить отдельные значения координат x, y и z, например, x=0,y=0,z=0, x=0,y=0,z=1, x=0,y=0,z=2,.... заранее спасибо....
1 ответ
Индексы отдельных потоков (координаты x, y, z) могут быть вычислены внутри ядра следующим образом:
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
int z = blockIdx.z * blockDim.z + threadIdx.z;
Имейте в виду, что количество потоков в блоке ограничено графическим процессором. Таким образом, размер блока, который вы создали, недопустим.
dim3 threads_query(32,32,32)
Он равен 32768 потоков на блок, который не поддерживается ни одним из текущих устройств CUDA. В настоящее время для графических процессоров с вычислительной способностью 2.0 и выше поддерживается максимум 1024 потока на блок, а для старых графических процессоров - до 512 потоков. Вы должны уменьшить размер блока, иначе ядро не запустится. Следует также отметить, что вы создаете трехмерную сетку, которая поддерживается только на графических процессорах CUDA Compute 2.0 и выше.
ОБНОВИТЬ
Предположим, что размеры ваших 3D-данных xDim
, yDim
а также zDim
тогда общая сетка потоковых блоков может быть сформирована следующим образом:
dim3 threads_query(8,8,8);
dim3 blocks_query;
blocks_query.x = (xDim + threads_query.x - 1)/threads_query.x;
blocks_query.y = (yDim + threads_query.y - 1)/threads_query.y;
blocks_query.z = (zDim + threads_query.z - 1)/threads_query.z;
Приведенный выше подход создает общее количество потоков, равное или превышающее общий размер данных. Дополнительные потоки могут вызвать недопустимый доступ к памяти. Так что выполняйте связанные проверки внутри ядра. Вы можете сделать это, передав xDim
, yDim
а также zDim
в качестве аргументов ядра и добавив следующую строку внутри ядра:
if(x>=xDim || y>=yDim || z>=zDim) return;