Найти тему
Решето

CUDA: иерархия нитей

Disclaimer: статья предназначена для тех, кто имеет представление о том, что такое CUDA, но путается при работе с сеткой.

Сетка состоит из блоков, блоки состоят из нитей...
Сетка состоит из блоков, блоки состоят из нитей...

Перед тем, как начать писать особо полезные программы на CUDA, нужно разобраться с иерархией нитей, то есть понять, как нити организованы.

Нить (thread) в CUDA – это последовательная программа, ответственная за решение части какой-то большой задачи. Нитей запускают всегда очень много и первая сложность, с которой сталкиваются программисты, это то, что нити организованы не линейно, а иерархично.

Верхним уровнем иерархии нитей в CUDA является сетка (grid). Сетка может быть одномерной, двумерной или трёхмерной.

Сетка состоит из блоков (block), которые тоже могут быть максимум трёхмерные.

Конфигурацию сетки и блоков мы задаём при вызове вычислительного ядра (kernel), например:

sum<<<1, 32>>(a) # да, Дзен до сих пор не умеет оформлять код

запустит 32 потока в 1 (одном) блоке, то есть

  1. будет создана сетка из одного блока
  2. в каждом блоке (а у нас он один) будет за запущено 32 нити

Чтобы убедиться, что это так, я написал маленькую программку (where.cu, запускать через nvcc where.cu && ./a.out), которая просто выводит на экран координаты каждого запущенного потока. И для конфигурации сетки выше она вывела (ожидаемо):

block(0, 0, 0) -> thread(0, 0, 0)
block(0, 0, 0) -> thread(1, 0, 0)
...
block(0, 0, 0) -> thread(31, 0, 0)

Чтобы лучше понять иерархию нитей, можно позапускать where.cu с разными настройками сетки:

  • where<<<dim3(2, 2, 2), 32>>>();
  • where<<<dim3(2, 2, 2), dim3(2, 2, 2)>>>();

Разобравшись с иерархией потоков в CUDA можно начинать думать о том, как отображаются данные, используемые в задаче на потоки. Но это уже другая история =)