CUDA определяет потоки на блок, блоки на каждую сетку

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

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

40
08 дек. '10 в 21:58
источник поделиться
4 ответов

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

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

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

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

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

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

65
16 окт. '12 в 22:11
источник

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

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

16
09 дек. '10 в 7:54
источник

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

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

14
08 дек. '10 в 22:20
источник

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

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

2
08 нояб. '11 в 23:03
источник

Посмотрите другие вопросы по меткам или Задайте вопрос