Каждый раз, когда встает заветный вопрос, апгрейдить ли карточки в серверной или нет, я просматриваю подобные статьи и смотрю такие видосы (нет, маркетинговым материалам от Nvidia конечно верить нельзя, как показал недавний кейс с числом CUDA-ядер).
Канал "Этот Компьютер" очень сильно недооценен, но автор не занимается ML. А в целом при анализе сравнений акселераторов для ML в глаза как правило бросаются несколько вещей:
- Авторы учитывают как правило только "адекватность" для рынка новых карт в США;
- Рейтинги далеки от народа и делаются на весьма стандартных сетках (что наверное в целом хорошо) без деталей;
- Популярная мантра тренировать все более гигантские сетки вносит свои коррективы в сравнения;
Не нужно быть семи пядей во лбу, чтобы знать очевидный ответ на вопрос "а какая карта лучше?": карточки серии 20* в массы не пошли, 1080 Ti с Авито до сих очень привлекательны (и не особо дешевеют как ни странно, вероятно по этой причине).
Все это прекрасно и вряд ли стандартные бенчмарки сильно врут, но недавно я узнал про существование технологии Multi-Instance-GPU для видеокарт А100 и нативную поддержку TF32 и мне пришла идея поделиться своим опытом реального тестирования карточек на архитектуре Ampere (3090 и А100). В этой небольшой заметке я постараюсь ответить на вопросы:
- Стоит ли свеч обновление на Ampere? (спойлер для нетерпеливых — да);
- Стоят ли своих денег A100 (спойлер — в общем случае — нет);
- Есть ли кейсы, когда A100 все-таки интересны (спойлер — да);
- Полезна ли технология MIG (спойлер — да, но для инференса и для очень специфичных случаев для обучения);
За деталями прошу под кат.
Простые Вещи
Давайте сразу обратим внимание на слона в комнате. На момент написания этой заметки:
- 3090 довольно сложно купить и продаются они примерно с 30-40% премией. Причем нехватки новых карт есть не только в СНГ;
- A100 почти невозможно купить. Партнеры Nvidia говорили что в РФ наличии есть 1 штука, потом приедет еще несколько штук;
- Я не особо искал, но с наскоку я не нашел информации насколько PCIE версия A100 совместима с обычными ATX платформами (именно на этот вопрос партнеры Nvidia не ответили, но я предполагаю, что в картах нет своего кулера и предполагается установка в серверное шасси с "громким" феном);
- 3080 и более младшие модели (хотя они очень интересны по цене, а особенно для игр) не тестировали, т.к. у нас их нет, а не рассматривали их из-за размера памяти (я наивно предполагал, что получится крутить несколько сеток на 1 карте, но там все работает несколько иначе);
По понятным причинам холивор — кормить или не кормить Амазон — выносим за скобки. Уверен, что среди комментаторов найдутся свидетели церкви Амазона, но свой риг как правило "окупается" против облачных цен (особенно если собирать из дешевых компонентов) где-то за полгода-год использования.
Охлаждение
Если верить утилитам от Nvidia, то 3090 и А100 на 15-20 градусов холоднее, чем Maxwell и Pascal. Я не проводил точные замеры, но в среднем ситуация такая:
- 4 * 1080 Ti (Pascal) с минимальными хаками по охлаждению работают в диапазоне 75-80С под 100% нагрузкой;
- 3 * Titan X (Maxwell) работали в районе 85С под 100% нагрузкой;
- 3 * 3090 (Ampere) работают в диапазоне 60-70С под 100% нагрузкой;
- Нигде не применялся ни разгон, ни ограничения по питанию карт или скорости кулеров, все "из коробки";
- Все карты имеют "турбину", то есть выталкивают тепло из корпуса;
На вопрос "почему" — есть 3 гипотезы:
- Новый техпроцесс;
- У 3090 немного другая форма самой карты, размер вентилятора заметно больше, размер отверстия на задней панельке сильно больше;
- 3090 кажется тяжелее (может кто-то знает где найти точные цифры, карт нет под рукой сейчас);
Наглядная иллюстрация отличий карточек, может кто-то из комментариев подскажет диаметр вентилятора?
Наивные Метрики
Сначала, чтобы удостовериться, что драйвера работают верно (а когда они работали неверно, цифры были другие совсем), давайте протестируем все доступные карточки с помощью gpu-burn
. Получается такая картина, которая очень сильно коррелирует с тем, что рисуют в обзорах.
Test | GPU | Gflop/s |
---|---|---|
./gpu_burn 120 |
Titan X (Maxwell) | 4,300 |
./gpu_burn 120 |
1080 Ti (Pascal) | 8,500 |
./gpu_burn 120 |
3090 (Ampere) | 16,500 |
./gpu_burn 120 |
A100 (wo MIG) | 16,700 |
./gpu-burn -tc 120 |
3090 (Ampere) | 38,500 |
./gpu-burn -tc 120 |
A100 (wo MIG) | 81,500 |
MIG не тестировался тут, дальше в статье увидите почему.
Цена Вопроса
Тут важно отметить, что 1080 Ti и Titan X мы покупали с рук условно "новые" (менее года использования). Не будем останавливаться лишний раз на холиворах про майнеров и политику ценообразования Nvidia, но если бережно использовать даже б/у игровые карты — их срок службы где-то 3-4 года. Цены и характеристики указаны примерные. A100 по информации от партнеров Nvidia в России в продаже имеется до нового года одна. Когда 1080Ti были доступны новыми, цены колебались примерно от 50к до 100к рублей.
GPU | Mem | Цена |
---|---|---|
Titan X (Maxwell) | 12G | 10,000 рублей (Авито) |
1080 Ti | 11G | 25,000 рублей (Авито) |
3090 (Ampere) | 24G | 160,000+ рублей (новая) |
A100 (wo MIG) | 40G | US$12,500 (новая) |
Думаю очевидные выводы дальше читатели сделают сами.
Пробуем 3090 и A100 c MIG
Пробуем 3090
А теперь переходим к самому интересному — к реальным тестам и собираем грабли на реальных задачах. В теории кажется, что если по памяти и вычислительным способностям 3090 или А100 в 2-3 раза превосходят 1080 Ti, то 1 такая карточка может заменить 2-3 1080 Ti и на стандартном сервере с 4 полноценными PCIE портами можно получить аналог сервера с 12 картами? Ну или можно ли взять допустим 3-4 PCIE версии A100 и получить очень мощный сервер, разделив каждую из них на несколько compute instance с использованием MIG?
Короткий ответ — нет, более длинный ответ — тоже нет, но с многочисленными оговорками.
Зачем спросите? Да просто серверные решения, которые полноценно поддерживают 8 — 16 видеокарт даже в минимальной разумной конфигурации по цене выходят в 4-5 раз дороже, чем стандартные ATX решения. А DGX Workstation или DGX продаются еще с примерно 50% премией к своей аналогичной сборке, если собирать на базе платформ от Mikrotik или Gigabyte.
Производители карт не торопятся выпускать полноценные однослотовые решения (кроме PNY c серией Quadro, но это отдельная история и скорее для дизайна или инференса). Конечно можно собрать кастомный водяной контур на 7 карточек (было несколько моделей материнских плат с 7 полноценными PCIE портами), но это "сложно" и неясно где такое размещать (да и игра не стоит свеч). С приходом PCIE 4.0 привлекательность таких решений по идее должна вырасти, но я пока не видел ничего интересного на рынке.
Пара огоровок про задачу на которой тестировали:
- Задача — тренировка Spech-to-Text сетки на украинском датасете;
- Из-за самой задачи экспериментально оптимальный размер батча на один процесс — 50 — не получается увеличивать без потерь в скорости сходимости;
- Именно на этой задаче AMP у нас не работает (хотя работает на других при прочих равных, мы пока не поняли почему), но это скорее оптимизация. То есть дело не в железе, а в задаче. На других задачах — работает, поэтому вынесем за скобки;
- Важая оговорка — поскольку по сути эта задача это sequence-to-sequence, то в общем случае построение батчей тут не совсем тривиально. Файлы разной длины попадают в батч только с файлами примерно такой же длины (чтобы снизить впустую потраченные ресурсы на обработку падинга), но размер батча статический для упрощения сравнений и более быстрой сходимости;
- Динамический размер батча и просто его увеличение тестировали, но это особо не влияет на скорость и скорость сходимости (или ухудшает);
Вопреки тренду делать все более гигантские сети, мы наоборот занимаемся миниатюризацией наших алгоритмов и пытаемся делать наши сети все более эффективными. Поэтому вопрос параллелизации и ускорения обучения сетей интересен в первую очередь за счет увеличения числа воркеров, а не размера сетей и вычислительных возможностей ускорителей.
И тут мы наталкиваемся на первый подводный камень — Distributed Data Parallel из PyTorch (DDP, оптимальный способ масштабирования сетей на "много" видеокарт) из коробки по сути настроен только на 1 процесс на 1 карте. То есть 1 процесс может использовать 1+ карту. 2 процесса не могут использовать 1 карту, даже если там есть большой запас по IO / compute / RAM. В старых версиях драйверов явного ограничения нет и на 1080 Ti 2 процесса на 1 карте запускаются (но получется прирост по скорости всего на 5-10% вместо 40-50%). На новых картах — туда уже впилили exception.
RuntimeError: NCCL error in: /opt/conda/conda-bld/pytorch_1603729096996/work/torch/lib/c10d/ProcessGroupNCCL.cpp:784, invalid usage, NCCL version 2.7.8
Но не все так печально и плохо. Может из-за какой-то низкоуровневой магии в драйверах, может из-за TF32 (надеюсь тут знатоки подскажут), может из-за наработок в MPS 3090 ведут себя немного иначе на нашем бенчмарке:
- При прочих равных и неизменных параметрах они используют больше памяти чем Titan X и 1080 Ti (~16 GB вместо 7-8 GB);
- Скорость примерно в 3 раза выше, чем с Titan X (Maxwell);
- [Нужно еще точно замерить скорость на 1080 Ti];
- Утилизация карт на высоком уровне — более 90%;
При попытках запускать 2 DDP воркера на 1 карте мы просто получаем ошибку, при попытке тренировать 2 сетки "одновременно" мы получаем кратное замедление, при увеличении батча — прирост по скорости незначительный. Тайминги на 2 * 3090 примерно такие:
| Epoch time, m | Type | Workers | Batch | Params |
|-----------------|------|---------|---------|----------------------|
| exception | DDP | 4 | 50 * 4 | |
| 3.8 | DDP | 2 | 50 * 2 | |
| 3.9 | DDP | 2 | 50 * 2 | cudnn_benchmark=True |
| 3.6 | DDP | 2 | 100 * 2 | |
Для полноты рассказа, важно еще отметить что у Nvidia есть MPS который якобы позволяет крутить 2 процесса на картах без переключения контекста, а в PyTorch есть встроенный RPC-фреймворк. Но первый я просто не смог адекватно использовать без очень непонятных низкоуровневых ошибок, а второй требует радикального переписывания кода и радикально усложняет код для тренировки моделей (хотя очень интересен долгосрочно).
Так, с 3090 все понятно. Две карточки она не заменит конечно, но сама по себе, даже имея "лишнюю" память (повторюсь, мы тренируем маленькие сети), работает в 2-3 раза быстрее. Эквивалентно ли это наличию 2-3 карт, зависит от задачи.
TLDR:
- Вы можете просто заменить карты с турбиной в своем риге на 3090 (единственный момент — в 3090 2 8-пиновых коннектора для питания, но на рынке есть блоки питания по 2000-Ватт которые точно могут запитать 4-5 таких карт, опять же никто не отменял синхронизацию 2 блоков питания);
- При этом скорее всего температура карт снизится на 10-20 градусов Цельсия;
- Эти карты сейчас стоят дорого и находятся в дефиците (и, наверное вряд ли пойдут в массы), но если для вас самый дорогой ресурс это время — то это интересный вариант;
- Если большой размер памяти для вас критичен — у вас по сути нет выбора;
Пробуем A100 с MIG
Посмотрев на метрики, доступность и цену карт, А100 на первый взгляд вообще не кажется интересным вариантом, разве что в облаке на 3 дня натренировать 1 большую сетку на небольшом не сильно приватном датасете. Также если вашим алгоритмам сильно помогает AMP / FP16, то А100 может существенно добавить скорости.
Но в A100 есть интересная технология MIG (Multi Instance GPU). По сути она позволяет разбить одну "большую и мощную" карточку на набор маленьких "подкарточек" и дальше создать виртуальные Compute Instances, к которым можно обращаться как к отдельным картам.
Там довольно много деталей, за ними откройте документацию, но там доступны такие пресеты:
+--------------------------------------------------------------------------+
| GPU instance profiles: |
| GPU Name ID Instances Memory P2P SM DEC ENC |
| Free/Total GiB CE JPEG OFA |
|==========================================================================|
| 0 MIG 1g.5gb 19 0/7 4.75 No 14 0 0 |
| 1 0 0 |
+--------------------------------------------------------------------------+
| 0 MIG 2g.10gb 14 0/3 9.75 No 28 1 0 |
| 2 0 0 |
+--------------------------------------------------------------------------+
| 0 MIG 3g.20gb 9 0/2 19.62 No 42 2 0 |
| 3 0 0 |
+--------------------------------------------------------------------------+
| 0 MIG 4g.20gb 5 0/1 19.62 No 56 2 0 |
| 4 0 0 |
+--------------------------------------------------------------------------+
| 0 MIG 7g.40gb 0 0/1 39.50 No 98 5 0 |
| 7 1 1 |
+--------------------------------------------------------------------------+
Доступные конфигурации
Возникает вопрос, а что если наша сетка маленькая, и A100 в теории (хотя бы на FP16) должна быть в 2 раза мощнее чем 3090? Можно ли взять 4 A100 и сделать из них допустим 12 видеокарт аналогичных по памяти и мощности 1080 Ti? Можно ли на этих многочисленных "микро-картах" тренировать нейросети так же как на нескольких обычных?
Ответим на вопросы по одному. Тут нам поможет как сама документация, так и совсем свежий блог пост от самой Nvidia.
В документации есть такой абзац:
MIG supports running CUDA applications by specifying the CUDA device on which the application should be run. With CUDA 11, only enumeration of a single MIG instance is supported.
CUDA applications treat a CI and its parent GI as a single CUDA device. CUDA is limited to use a single CI and will pick the first one available if several of them are visible. To summarize, there are two constraints:
- CUDA can only enumerate a single compute instance
- CUDA will not enumerate non-MIG GPU if any compute instance is enumerated on any other GPU
Note that these constraints may be relaxed in future NVIDIA driver releases for MIG.
Сначала, когда я его прочитал, мне показалось, что он означал только что нельзя распилить 2 карты, а можно использовать только одну. После того, как я попробовал поиграться с реальной картой, оказалось, что фреймворк внутри контейнера видит только 1 "карту" (причем видимо выбирает он только "первую"). Причем если мы внимательно прочитаем те примеры, которые Nvidia приводит в своем блоге, они по сути все относятся к сценарию "1 контейнер — 1 кусочек карты" или "тюнинг 7 маленьких моделей параллельно".
Еще там есть вот такой пассаж:
There is no GPU-to-GPU P2P (both PCIe and NVLINK) support in MIG mode, so MIG mode does not support multi-GPU or multi-node training. For large models or models trained with a large batch size, the models may fully utilize a single GPU or even be scaled to multi-GPUs or multi-nodes. In these cases, we still recommend using a full GPU or multi-GPUs, even multi-nodes, to minimize total training time.
Если использовать MIG по прямому назначению, то есть делить карту на физические кусочки (slices), назначать им Compute Instances и прокидывать их в изолированные контейнеры — то все работает как надо. It just works.
Итоговые Замеры
Тут не совсем идеальные сравнения (на Титане у меня был DP а не DDP), да и на A100 в итоге я не стал гонять эксперименты на 10, 20, 30 часов и впустую (зачем греть атмосферу), но я замерил время на 1 эпохе.
Когда крутишь 1 сетку на A100 утилизация не достигает даже и половины — ну то есть если бы ее можно было распилить на 2-3 карты, все было бы прекрасно
Avg epoch time, m | Workers | Batch | GPUs | CER @10 hours | CER @20 h | CER @30 h | Comment |
---|---|---|---|---|---|---|---|
4.7 | 2, DDP | 50 * 2 | 2 * 3090 | 14.4 | 12.3 | 11.44 | Close to 100% utilization |
15.3 | 1, DP | 50 | 2 * Titan X | 21.6 | 17.4 | 15.7 | Close to 100% utilization |
11.4 | 1, DDP | 50 * 1 | 1 * A100 | NA | NA | NA | About 35-40% utilization |
TBD | 2, DDP | 50 * 2 | 2 * 1080 Ti | TBD | TBD | TBD |
На 1080 Ti ресурсы были только чтобы прогнать 1 эпоху.
Выводы
Выводы про 3090:
- Если вынести за скобки вопрос доступности, то апгрейд стоит делать. Вы получите минимум x2 по скорости. Если у вас работает AMP — то может даже и все x3-x4;
- С учетом роста производительности, цена кажется немного завышенной, но не заоблачной. Понижение цены где-то на 30-40% как мне кажется было бы адекватным;
- Когда выходило новое поколение карт все беспокоились насчет охлаждения. Она на удивление холодная;
- Единственная беда — карточка просит 2 8-пиновых коннектора для питания;
Выводы про A100:
- Если судить по цене деленной на производительность, карта не очень интересная (наценка в 2-3 раза против 3090);
- То, что Nvidia сделала технологию для эффективного использования для инференса — это круто, а то карты стали уж слишком большими и крутыми;
- Если вы можете использовать обычные игровые карты (те же 1080 Ti или PNY Quadro) для инференса, то они представляют сильно больший value for money;
- Есть большой нераскрытый потенциал в развитии технологии MIG;
- Если вам нужно реально 40 GB памяти и много compute, то альтернатив особо нет;
- Неясен вопрос с установкой PCIE версии в обычные ATX корпуса без кастома, "колхоза" или воды ;
Update 1
Добавил gpu-burn вместе с CUDA_VISIBLE_DEVICES
Попробую указать CUDA_VISIBLE_DEVICES
внутри каждого процесса PyTorch
Test | GPU | Gflop/s | RAM |
---|---|---|---|
./gpu_burn 120 | A100 // 7 | 2,400 * 7 | 4.95 * 7 |
./gpu_burn 120 | A100 // 3 | 4,500 * 3 | 9.75 * 3 |
./gpu_burn 120 | A100 // 2 | 6,700 * 2 | 19.62 * 2 |
./gpu_burn 120 | A100 (wo MIG) | 16,700 | 39.50 * 1 |
./gpu-burn -tc 120 | A100 // 7 | 15,100 * 7 | 4.95 * 7 |
./gpu-burn -tc 120 | A100 // 3 | 30,500 * 3 | 9.75 * 3 |
./gpu-burn -tc 120 | A100 // 2 | 42,500 * 2 | 19.62 * 2 |
./gpu-burn -tc 120 | A100 (wo MIG) | 81,500 | 39.50 * 1 |
Update 2
График утилизации карты когда запущено 3 параллельных gpu-burn
через MIG
Update 3
В итоге я смог завести DDP с MIG на PyTorch.
Надо было сделать так и везде использовать нулевой (первый) дивайс.
def main(rank, args):
os.environ["CUDA_VISIBLE_DEVICES"] = args.ddp.mig_devices[rank]
import torch
...
С NCCL я получил такой же exception. Поменяв nccl
на gloo
оно запустилось… но рабортало оооочень медленно. Ну условно в десять раз медленнее и утилизация карты была на очень низком уровне. Думаю нет смысла дальше копать.
snakers4 Автор
Показывал статью знакомым, добавлю еще ряд оговорок:
gpu-burn
;gpu-burn
и тест на 1 "слайсике" я не делал прокидывая внутрь контейнера 1 "маленький" слайсик. По нагрузке очевидно, что при 2 слайсиках будет максимум так же быстро как на всей карте A100 целиком, а параллелизация не выходит с MIG. А сgpu-burn
можно просто цифры разделить в уме согласно документации;