
Привет, Хабр! Это снова Ефим Головин, все еще старший MLOps-инженер в Selectel. В прошлой статье в попытках оценить перспективы AMD в ML мы внезапно погрузились в дебри документации NVIDIA. А теперь пора взглянуть на то, что происходит, собственно, у AMD. Забегая вперед, могу сказать, что во многом «красные» оперируют очень похожими терминами. Это вполне понятно и логично, поскольку и NVIDIA их не из воздуха взяли. Все это так или иначе корнями уходит в идеи, появившиеся и описанные задолго до появления терминов «CUDA», «SM», архитектуры Tesla и т. д.
Закажите сервер с GPU от AMD. Под капотом: 16-ядерный AMD RyzenTM 9 9950X 3,4 ГГц, видеокарта AMD Radeon RX 7900XT 20 ГБ GDDR6, 48 ГБ RAM DDR5 и 1 000 ГБ SSD NVMe M.2.
В прошлый раз мы пробежались по тому, что и как называется у NVIDIA. Особое внимание уделили терминам «Compute Capability» и «SM». И если помните, тогда для понимания первого термина пришлось разобраться со вторым. При этом мы тактично избежали разговоров о том, что такое «kernel», «Warp», «Thread», «Block», «Grid».
Что же, разбираясь с терминологией AMD, я попробую исправиться.
Используйте навигацию, если не хотите читать текст целиком:
→ Compute Unit
→ LLVM и HIPCC
→ Что еще за GFX
→ Logical vs Actual
→ Что еще за Warp
→ Итог
→ Что дальше
Compute Unit
В прошлый раз, разбирая значение «Compute Capability» от NVIDIA, мы уперлись в то, что для понимания данного термина нужно сначала понять, что такое «SM». Так вот, с AMD похожая история. Только теперь нам придется разобраться с тем, что такое «Compute Unit».
Итак, Compute Unit (CU) от AMD — это — барабанная дробь…

— это аналог Stream(ing) Multiprocessor от NVIDIA.
Прежде всего, я бы рекомендовал почитать пост «Demystifying GPU Compute Architectures», в котором как раз упор делается на то, чтобы сравнить эти два вычислительных блока. Впрочем, кое-что мы подсветим и здесь.
Поскольку впервые термин Stream(ing) Multiprocessor был введен в рамках архитектуры Tesla, то вполне логично было бы взглянуть на ее прямого конкурента со стороны AMD, а именно — TeraScale:

Есть только одна маленькая загвоздка: в архитектуре TeraScale отсутствует Compute Unit. Вот как выглядит чип на базе архитектуры TeraScale:

Схема взята из блога AMD на Reddit. Для сравнения поглядим на то, как выглядит архитектура Tesla:

Если дальше зуммировать и смотреть на более мелкие блоки, то первое, что может прийти в голову — сопоставление TPC (Texture/Processor Cluster) и SIMD Core (Single Instruction Multiple Data):
![]() |
![]() |

Кажется, что ближайший аналог Stream(ing) Multiprocessor в случае архитектуры TeraScale — это именно Stream Processing Unit, состоящий, как и Stream(ing) Multiprocessor, из базовых арифметико-логических модулей, общей памяти и управляющих элементов. Впрочем, данное сопоставление довольно грубое и основано сугубо на том, что написано по поводу данных вычислительных блоков в документе «NVIDIA TESLA:AUNIFIED GRAPHICS AND COMPUTING ARCHITECTURE» и в статье «Part 2 — An Architectural Deep-dive into TeraScale, GCN & RDNA» на Reddit.
Так а что же там по поводу CU? Этот-то элемент откуда берется? И вообще, с чего мы решили, что это прямой аналог SM?
Во-первых, об этом прямо говорит документация AMD:

А во-вторых, об этом идет речь в видео «Introduction to AMD GPU Hardware», выложенном на YouTube-канале AMD:

Так вот, Compute Unit как вычислительный блок появляется в семействе архитектур Graphics Core Next (GCN).

LLVM и HIPCC
Теперь вопрос: есть ли в мире AMD некий аналог sm_XX и compute_XX? Скажем, что-нибудь вроде cu_XX и compute_XX.
Вполне логично предположить, что, как и в случае с NVIDIA, AMD не будет способен гарантировать совместимость на уровне бинарного кода. А чтобы обеспечить переносимость программ, нужно будет внедрять нечто по аналогии с тем, как это сделано у NVIDIA.
Это становится еще логичнее на фоне фразы из документации: вычислительные блоки архитектур CDNA и RDNA основаны на вычислительных блоках архитектуры GCN.

То есть ожидаемым вариантом — с моей точки зрения — была бы похожая схема компиляции кода, позволяющая собирать из исходного кода бинарь, который можно выполнить на разных GPU.
И вот тут опять нужно немного поговорить о компиляции, а прежде обратить внимание на прямой аналог NVCC от NVIDIA — HIPCC. Давайте интереса ради проверим, соотносится ли как-то HIPCC и LLVM. Беглый гуглинг позволяет понять, что, как и NVCC, HIPCC основан на LLVM:

К моему сожалению, качество официальной документации HIPCC оставляет желать лучшего. На текущий момент (20 мая 2025) это буквально три странички:

Непосредственно в этой документации вы особо ничего полезного не найдете. Для сравнения можете взглянуть на аналогичную документацию по NVCC.
Тем не менее, если еще немного покопаться, то можно, во-первых, наткнуться на документацию по всему форку LLVM-проекта AMD. Там в числе прочего есть замечательная табличка, в которой перечислены все инструменты, необходимые для процесса компиляции кода:

А во-вторых, можно найти раздел «Compiler reference guide», в котором есть другая интересная табличка:

И вот тут уже становится интересно.
Что еще за GFX
На этом моменте мы довольно быстро осознаем, что gfxYZT — это что-то очень похожее на аналог sm_XY. И действительно, поискав немного, находим описание всех возможных комбинаций YZT и того, что этим комбинациям соответствует:

Видим также, что полный набор значений gfx’ов указан в секции Processors. И если пойти и посмотреть в эту табличку, то… все станет очень-очень плохо:

Во-первых, gfx’ы появляются далеко не сразу. Во-вторых, какое-то четкое соответствие между YZT’ами и какими-то понятными изменениями установить не удалось.
Тем не менее, покопавшись еще немного, я набрел на другую не менее интересную табличку:
А вот теперь уже стало понятнее! Глядя на эту табличку, можно сделать вывод, что есть общее название семейства архитектур, а именно:
В рамках каждого семейства есть ключевой (Core) набор инструкций (ISA). Также в рамках каждого семейства есть несколько поколений:
- GCN: GCN 1, GCN 2, GCN 3, GCN 4, GCN 5,
- CDNA: CDNA 1, CDNA 2, CDNA 3,
- RDNA: RDNA 1, RDNA 2, RDNA 3.
Каждому поколению соответствует свой ключевой набор инструкций. Здесь стоит оговориться, что связь между поколением архитектуры и ключевым набором инструкций — не один к одному. Например, GFX9 соответствует аж четырем поколениям архитектур, причем одно поколение вообще из другого семейства. Каждому ключевому набору инструкций соответствует свой набор вариаций и модификаций.
По сути, YZT отвечают за то, чтобы пронумеровать ключевой набор инструкций и его модификацию. Y отвечает за ключевой набор инструкций — он может быть двузначным числом. ZT отвечает за конкретную модификацию ключевого набора.
Тут же может возникнуть вопрос: а что же там по поводу сборки кода под несколько таких gfxYZT? Должен же быть у AMD аналогичный способ. Разумеется, он есть. В документации очень сжато описывается, как компилируется код. Если вкратце, то, как и в случае с NVIDIA, у нас есть JIT и FatBinary.
По поводу JIT-компиляции есть прямо отдельная страница в документации и, надо сказать, это не самая тривиальная история (для того, кто только вкатывается, уж точно). Надо писать код, который будет через вызов функций библиотеки
<hip/hiprtc.h>
создавать структуры, описывающие код, и в рантайме вытаскивать свойства GPU, в числе которых должна находиться информация и о конкретном gfxYZT, под который нужно скомпилировать код, передав gfxYZT с помощью параметра --gpu-architecture
.В этом смысле сборка «Толстяка Бина» (FatBinary) у AMD выглядит сильно проще:

Дабы немного потренироваться на сборке фатбинарей, можно воспользоваться туториалом по сборке своеобразного «Hello, world!» в мире GPGPU, а именно — Single-precision A times X Plus Y (SAXPY).
Последний вопрос, который у меня остался: почему GFX? Хотя, думаю, тут ответ довольно простой. Сюрприз: это сокращение от graphics.

Logical vs Actual
Мы более или менее подробно разобрали аналог SM’ок. Стало понятно, что железная составляющая вполне себе прямо влияет на то, как мы пишем код, как его компилируем и т. д.
Тем не менее, остаются еще Warp’ы, Thread’ы. Block’и и Grid’ы. Что это? Зачем это? Почему это? Все это очень интересные вопросы. Давайте же на них и попробуем ответить.
И начать здесь я предлагаю с замечательного обсуждения на Stack Overflow. В нем прослеживается мысль о том, что помимо логической организации кода есть еще то, как организовано железо внутри и как одно согласуется с другим:
«...That's the logical hierarchy. You really only need to understand the logical hierarchy to implement a function on the GPU, however to get performance you need to understand the hardware too which is SMs and SPs».
Это действительно дельная мысль, поскольку она позволяет четко отделить сущности, относящиеся к логической организации, от сущностей, относящихся к физическому устройству GPU и тому, как внутри него выполняется код. Давайте это и попробуем сделать.
Итак, логически код организован следующим образом (взято из оригинальной статьи по архитектуре Tesla):

Дабы сильно не растекаться мыслью по древу, сошлемся на раздел «Cooperative thread array or thread block» в уже упомянутой выше оригинальной статье по архитектуре Tesla и на раздел «Thread Hierarchy» в документации. Если кратко, то:
- один CUDA-kernel исполняется в рамках одного CUDA-thread,
- CUDA-thread’ы группируются в CUDA-thread-block’и,
- CUDA-thread-block’и группируются в CUDA-Grid’ы.
В документации данная иерархия обозначена вот так:

Вопрос: а как логика распараллеливания устроена у AMD? Ответ есть в видео «Introduction to AMD GPU Hardware».
Как и у NVIDIA, у AMD есть своя парадигма для организации параллельных вычислений — Heterogeneous-computing Interface for Portability (HIP). Подробно ее сейчас разбирать не будем, т. к. это вообще тема отдельной статьи. Сейчас мы это просто зафиксируем, дабы ниже по тексту было понятно, о чем речь.
Итак:
- один HIP-kernel исполняется в рамках одного HIP-thread’а,
- HIP-thread-ы объединяются в HIP-Workgroup’ы,
- HIP-Workgroup-ы объединяются в HIP-Grid’ы.
В документации данная иерархия обозначена вот так:

Что еще за Warp
Стоп! А откуда тут взялись Warp’ы? И почему тут не Workgroup’ы, а Block’и? Давайте сначала с первым вопросом разберемся. Что вообще такое Warp? Для этого откроем опять же оригинальную статью по архитектуре Tesla и, что называется, исполним Ctrl/Cmd+F:
«To manage and execute hundreds of threads running several different programs efficiently, the Tesla SM uses a new processor architecture we call single-instruction, multiple-thread (SIMT). The SM’s SIMT multithreaded instruction unit creates, manages, schedules, and executes threads in groups of 32 parallel threads called warps».
Здесь говорится, что внутри SM’ов thread’ы организуются в группы по 32 параллельных thread’а — warp’ы. Далее по тексту следует еще одна замечательная фраза:
«The term warp originates from weaving, the first parallel thread technology».
Здесь авторы статьи любезно поясняют, что слово «warp» берет начало из… ткачества! Обожаю, когда в статьях обращают внимание на то, откуда взялись термины, которыми они оперируют! Без шуток, это очень круто.
Подумать только, ткачество! Технология палеолита (если верить Большой российской энциклопедии) стала родоначальницей современных параллельных вычислений! Если интересно, то вот вам замечательная статья с кратким историческим экскурсом в эту технологию. Но вернемся к NVIDIA.
Stream(ing) Multiprocessor, выполняя команду в соответствии с архитектурой SIMT (Single instruction, multiple threads), нарезает CUDA-thread’ы на Warp’ы, по 32 CUDA-thread’а на один Warp.
Так вот, возвращаемся к вопросу, откуда тут (в смысле у AMD) взялись Warp’ы. И почему тут не Workgroup’ы, а Block’и? Дело в том, что AMD реализует все ту же SIMT-архитектуру:

Ладно, с этим вопросом более или менее разобрались. Второй вопрос: почему тут не Workgroup’ы, а Block’и? Возвращаемся к уже упомянутому выше видео:

То есть в рамках терминологии AMD CUDA-thread-block (или просто Block) — это и есть HIP-Workgroup’а. А есть ли для Warp’а похожий аналог в терминологии AMD? Да, есть:

И вся эта терминологическая эквилибристика сводится вот в такую замечательную табличку:

Как видите, сущностно особо ничего не меняется.
Итог
Давайте попробуем подвести итог.
- AMD и NVIDIA очень похожи с точки зрения компиляции кода, переносимого на разные архитектуры.
- Оба компилятора (NVCC и HIPCC) реализуют LLVM’ный бэкенд, предназначенный для компиляции device-кода, подходящего для конкретной версии ISA.
- Структурно ближайший аналог SM, это CU.
- AMD и NVIDIA реализуют одну и ту же SIMT-архитектуру.
- Через это логическая организация кода в HIP и CUDA довольно сильно похожа.
Что дальше
Получилось немного скомкано, но лиха беда начало. Надо так или иначе от чего-то отталкиваться, чтобы начать отвечать на насущные вопросы. А каковы они, эти вопросы? Что дальше хотелось бы понять?
Дальше, конечно, базово хотелось бы ответить на несколько вопросов, которые показались насущными в контексте AI/DL/ML’ной темы.
- Можно ли запустить обучение ML-моделей на AMD? Насколько это сложно? Сложнее, чем на NVIDIA? Что там с установкой драйверов? Можно ли работать через Docker? Есть ли поддержка популярных фреймворков: TensorFlow, PyTorch, JAX и других?
- Можно ли запустить инференс ML-моделей на AMD? Есть ли поддержка популярных Inference-серверов: vLLM, Ollama или Triton Inference Server?
- Можно ли работать с AMD в Kubernetes? Есть ли какие-то аналоги GPU Operator’а, Device-плагина и других компонентов? Что имеется для мониторинга потребления ресурсов GPU (аналог NDCG)?
- Можно ли работать с Distributed ML на AMD? Что AMD предлагает в противовес NVLink, NVSwitch и InfiniBand? Есть ли у AMD что-то наподобие NCCL? Как это что-то работает? Поддерживают ли PyTorch, TensorFlow и другие фреймворки распределенное обучение на AMD’шных GPU?
- Дорого ли запустить ML-проект на AMD? Сколько стоит GPU от AMD? Как ценники на AMD’шные GPU сопоставляются с ценами на аналоги от NVIDIA?
- Выгодно ли запустить ML-проект на AMD? А стоит ли переход на AMD’шные GPU своих затрат? Проигрывают ли они по производительности и энергозатратам? Насколько сложно переучивать специалистов с NVIDIA- на AMD-стек?
Это не список будущих статей. Это, скорее, именно вопросы, на которые я постараюсь ответить в будущих публикациях. Кратко о чем-то я уже говорил на конференции I’ML, а сейчас хочу рассмотреть тему более подробно.