Как блоки / деформации / потоки CUDA отображаются на ядра CUDA?
Я использую CUDA в течение нескольких недель, но у меня есть некоторые сомнения по поводу распределения блоков / варпов / потоков.Я изучаю архитектуру с дидактической точки зрения (университетский проект), поэтому достижение максимальной производительности не является моей задачей.
Прежде всего, я хотел бы понять, правильно ли я понял эти факты:
Программист пишет ядро и организует его выполнение в виде сетки потоковых блоков.
Каждый блок назначается потоковому мультипроцессору (SM). После назначения он не может мигрировать на другой SM.
Каждый SM разбивает свои блоки на деформации (в настоящее время максимальный размер 32 потока). Все потоки в деформации выполняются одновременно на ресурсах SM.
Фактическое выполнение потока выполняется ядрами CUDA, содержащимися в SM. Не существует конкретного отображения между потоками и ядрами.
Если деформация содержит 20 потоков, но в настоящее время доступно только 16 ядер, деформация не будет выполняться.
С другой стороны, если блок содержит 48 потоков, он будет разделен на 2 деформации, и они будут выполняться параллельно при условии наличия достаточного объема памяти.
Если поток запускается на ядре, то он останавливается для доступа к памяти или для длительной операции с плавающей запятой, его выполнение может возобновиться на другом ядре.
Они правы?
Теперь у меня есть GeForce 560 Ti, поэтому в соответствии со спецификациями он оснащен 8 SM, каждое из которых содержит 48 ядер CUDA (всего 384 ядра).
Моя цель - убедиться, что каждое ядро архитектуры выполняет те же инструкции. Предполагая, что мой код не потребует большего количества регистров, чем те, что доступны в каждом SM, я представил различные подходы:
Я создаю 8 блоков по 48 потоков в каждом, так что каждый SM имеет 1 блок для выполнения. В этом случае будут ли 48 потоков выполняться параллельно в СМ (используя все доступные для них 48 ядер)?
Есть ли разница, если я запускаю 64 блока из 6 потоков? (Предполагая, что они будут отображаться равномерно среди SM)
Если я "погрузлю" GPU в запланированную работу (например, создав 1024 блока по 1024 потока в каждом), разумно предположить, что все ядра будут использоваться в определенный момент и будут выполнять те же вычисления (при условии, что потоки никогда не глохнет)?
Есть ли способ проверить эти ситуации с помощью профилировщика?
Есть ли какие-либо ссылки на этот материал? Я прочитал руководство по программированию CUDA и главы, посвященные аппаратной архитектуре, в разделах "Программирование массово параллельных процессоров" и "Проектирование и разработка приложений CUDA"; но я не мог получить точный ответ.
2 ответа
Две из лучших ссылок
Я постараюсь ответить на каждый ваш вопрос.
Программист делит работу на потоки, потоки на блоки потоков и блоки потоков на сетки. Распределитель вычислительных работ выделяет блоки потоков потоковым мультипроцессорам (SM). Как только блок потока распределяется по SM, ресурсы для блока потока распределяются (деформации и разделяемая память), и потоки разделяются на группы из 32 потоков, называемых деформациями. Когда варп выделен, он называется активным. Два планировщика варпа выбирают два активных деформации за цикл и отправляют деформации в исполнительные единицы. Для получения более подробной информации о исполнительных блоках и распределении команд см. 1 стр.7-10 и 2.
4 '. Существует сопоставление между laneid (индекс потоков в основе) и ядром.
5 '. Если деформация содержит менее 32 потоков, она в большинстве случаев будет выполняться так же, как если бы она имела 32 потока. Деформации могут иметь менее 32 активных потоков по нескольким причинам: количество потоков на блок не делится на 32, программа выполняет расходящийся блок, поэтому потоки, которые не выбрали текущий путь, помечаются как неактивные, или поток в деформации завершается.
6 '. Блок потока будет разделен на WarpsPerBlock = (ThreadsPerBlock + WarpSize - 1) / WarpSize. Для планировщиков деформаций не требуется выбирать два деформации из одного блока нитей.
7 '. Исполнительный блок не будет зависать от операции с памятью. Если ресурс недоступен, когда инструкция готова к отправке, она будет отправлена снова в будущем, когда ресурс будет доступен. Деформации могут останавливаться на барьерах, на операциях с памятью, операциях с текстурами, зависимостях данных,... Остановленный деформация не может быть выбран планировщиком деформации. В Fermi полезно иметь как минимум 2 приемлемых деформации за цикл, чтобы планировщик деформации мог выдавать инструкцию.
См. Ссылку 2 для различий между GTX480 и GTX560.
Если вы прочитаете справочный материал (несколько минут), я думаю, вы обнаружите, что ваша цель не имеет смысла. Я постараюсь ответить на ваши вопросы.
1 '. Если вы запустите ядро <<<8, 48>>>, вы получите 8 блоков каждый с 2 перекосами из 32 и 16 потоков. Нет никакой гарантии, что эти 8 блоков будут назначены различным SM. Если SM выделено 2 блока, то, возможно, каждый планировщик деформации может выбрать деформацию и выполнить деформацию. Вы будете использовать только 32 из 48 ядер.
2 '. Существует большая разница между 8 блоками из 48 потоков и 64 блоками из 6 потоков. Давайте предположим, что ваше ядро не имеет расхождения и каждый поток выполняет 10 инструкций.
- 8 блоков с 48 нитями = 16 основ * 10 инструкций = 160 инструкций
- 64 блока с 6 нитями = 64 основы * 10 инструкций = 640 инструкций
Чтобы получить оптимальную эффективность, разделение работ должно быть кратно 32 потокам. Аппаратные средства не будут объединять потоки из разных перекосов.
3 '. GTX560 может иметь 8 блоков SM * 8 = 64 блока за раз или 8 перекосов SM * 48 = 512 деформаций, если ядро не использует максимум регистров или разделяемой памяти. В любой момент времени часть работы будет активна на SM. Каждый SM имеет несколько исполнительных блоков (больше чем ядра CUDA). Какие ресурсы используются в любой момент времени, зависит от планировщиков деформации и набора команд приложения. Если вы не выполняете операции TEX, то блоки TEX будут простаивать. Если вы не выполните специальную операцию с плавающей запятой, блоки SUFU будут простаивать.
4 '. Параллельное шоу Nsight и Visual Profiler
а. выполненный МПК
б. выданный МПК
с. активные деформации за активный цикл
д. допустимые перекосы за активный цикл (только Nsight)
е. причины остановки варпа (только Nsight)
е. активные потоки в каждой выполненной инструкции
Профилировщик не показывает процент использования ни одного из исполнительных блоков. Для GTX560 приблизительная оценка будет выдана IPC / MaxIPC. Для MaxIPC предположим, что GF100 (GTX480) равен 2, GF10x (GTX560) равен 4, но цель 3 - лучшая цель.
"E. Если варп содержит 20 потоков, но в настоящее время доступно только 16 ядер, варп не будет работать".
это неверно. Вы путаете ядра в их обычном смысле (также используемом в процессорах) - количество "мультипроцессоров" в GPU, с ядрами в маркетинге nVIDIA ("наша карта имеет тысячи ядер CUDA").
Сама деформация может быть запланирована только на одно ядро (= многопроцессорный) и может одновременно запускать до 32 потоков; он не может использовать более одного ядра.
Число "48 деформаций" - это максимальное количество активных деформаций (деформации, которые могут быть выбраны, чтобы быть запланированными для работы в следующем цикле, в любом заданном цикле) на мультипроцессор, на графических процессорах nVIDIA с Compute Capability 2.x; и это число соответствует 1536 = 48 х 32 потоков.
Ответ на основе этого вебинара