CUDA определяет потоки на блок, блоков на сетку - PullRequest
51 голосов
/ 08 декабря 2010

Я новичок в парадигме CUDA. Мой вопрос заключается в определении количества потоков на блок и блоков на сетку. Играет ли в этом немного искусства и проб? Я обнаружил, что во многих примерах для этих вещей выбрано, казалось бы, произвольное число.

Я рассматриваю проблему, где я мог бы передать матрицы - любого размера - методу для умножения. Таким образом, каждый элемент C (как в C = A * B) будет вычисляться одним потоком. Как бы вы определили потоки / блок, блоки / сетку в этом случае?

Ответы [ 4 ]

83 голосов
/ 16 октября 2012

Как правило, вы хотите, чтобы ваши блоки / сетка соответствовали вашим данным и одновременно максимизировали занятость, то есть, сколько потоков активно одновременно.Основными факторами, влияющими на занятость, являются использование общей памяти, использование регистров и размер блока потоков.

Возможности обработки в графическом процессоре с поддержкой CUDA разделены на SM (потоковые мультипроцессоры), а количество SM зависит от фактическогокарты, но здесь мы сосредоточимся на одном SM для простоты (все они ведут себя одинаково).Каждый SM имеет конечное количество 32-битных регистров, разделяемую память, максимальное количество активных блоков и максимальное количество активных потоков.Эти числа зависят от CC (вычислительные возможности) вашего GPU и могут быть найдены в середине статьи в Википедии http://en.wikipedia.org/wiki/CUDA.

Прежде всего, размер блока вашего потока всегда должен быть кратным 32, потому чтоядра выдают инструкции в деформациях (32 потока).Например, если у вас размер блока 50 потоков, графический процессор по-прежнему будет выдавать команды для 64 потоков, и вы просто их теряете.

Во-вторых, прежде чем беспокоиться о совместной памяти и регистрах, попробуйте изменить размерваши блоки основаны на максимальном количестве потоков и блоков, которые соответствуют вычислительным возможностям вашей карты.Иногда есть несколько способов сделать это ... например, карта CC 3.0 каждый SM может иметь 16 активных блоков и 2048 активных потоков.Это означает, что если у вас 128 потоков на блок, вы можете разместить в своем SM 16 блоков, прежде чем достигнете ограничения в 2048 потоков.Если вы используете 256 потоков, вы можете уместить только 8, но вы все еще используете все доступные потоки и по-прежнему будете полностью заняты.Однако при использовании 64 потоков на блок будет использоваться только 1024 потока при достижении ограничения в 16 блоков, то есть только 50% занятости.Если использование общей памяти и регистров не является узким местом, это должно быть вашей главной задачей (кроме измерений ваших данных).

По теме вашей сетки ... блоки в вашей сетке для начала распределены по SM, а затем оставшиеся блоки помещаются в конвейер.Блоки перемещаются в SM для обработки, как только в этом SM появляется достаточно ресурсов для захвата блока.Другими словами, когда блоки завершаются в SM, новые перемещаются внутрь. Можно привести аргумент, что меньшие блоки (128 вместо 256 в предыдущем примере) могут завершаться быстрее, поскольку особенно медленный блок потребляет меньше ресурсов, ноэто очень сильно зависит от кода.

Что касается регистров и общей памяти, посмотрите на это далее, так как это может ограничивать вашу занятость.Общая память является конечной для всего SM, поэтому старайтесь использовать ее в количестве, которое позволяет как можно большему количеству блоков уместиться на SM.То же самое касается использования регистра.Опять же, эти числа зависят от вычислительных возможностей и могут быть найдены в виде таблицы на странице википедии.Удачи!

18 голосов
/ 09 декабря 2010

http://developer.download.nvidia.com/compute/cuda/CUDA_Occupancy_calculator.xls

Калькулятор занятости CUDA позволяет вычислить многопроцессорную занятость графического процессора данным ядром CUDA. Занятость мультипроцессора - это отношение активных деформаций к максимальному количеству деформаций, поддерживаемых в многопроцессорных графических процессорах. Каждый мультипроцессор на устройстве имеет набор из N регистров, доступных для использования потоками программы CUDA. Эти регистры являются общим ресурсом, который распределяется среди потоковых блоков, выполняемых на многопроцессорном компьютере. Компилятор CUDA пытается минимизировать использование регистров, чтобы максимизировать количество блоков потоков, которые могут быть активны в машине одновременно. Если программа пытается запустить ядро, для которого количество регистров, используемых на поток, превышает размер блока потока больше N, запуск завершится неудачей ...

15 голосов
/ 08 декабря 2010

За редкими исключениями, вы должны использовать постоянное количество потоков в блоке.Количество блоков в сетке определяется размером задачи, например размерами матрицы в случае умножения матрицы.

Выбор количества потоков в блоке очень сложен.Большинство алгоритмов CUDA допускают широкий диапазон возможностей, и выбор основан на том, что заставляет ядро ​​работать наиболее эффективно.Это почти всегда кратно 32 и не менее 64 из-за того, как работает аппаратное планирование потоков.Хороший выбор для первой попытки - 128 или 256.

3 голосов
/ 09 ноября 2011

Вам также необходимо учитывать общую память, поскольку потоки в одном и том же блоке могут обращаться к одной и той же общей памяти.Если вы разрабатываете что-то, что требует много разделяемой памяти, тогда может быть выгодно больше потоков на блок.

Например, с точки зрения переключения контекста, любое кратное 32 работает точно так же.Таким образом, для случая 1D запуск 1 блока с 64 потоками или 2 блоков с 32 потоками каждый не имеет значения для доступа к глобальной памяти.Однако, если рассматриваемая проблема естественно разлагается на 1 вектор длины 64, то первый вариант будет лучше (меньше затрат памяти, каждый поток может получить доступ к той же общей памяти), чем второй.

...