Как рассчитать индексы координат отдельных нитей в трехмерных сетках?

У меня есть трехмерная сетка, состоящая из 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;
Другие вопросы по тегам