![Гайд по использованию GPU в машинном обучении Гайд по использованию GPU в машинном обучении](https://habrastorage.org/getpro/habr/upload_files/9aa/54e/716/9aa54e716f8988260e0c9f822cf2ab6b.jpg)
Это перевод популярного лонгрида Тима Детмерса “Выбор графического процессора для глубокого обучения: мой опыт и советы“.
Глубокое обучение (Deep learning, DL) – область с высокими вычислительными требованиями, и выбор графического процессора будет в корне определять ваши возможности в этой сфере. Какие характеристики важны при выборе нового GPU? Оперативная память GPU, ядра, тензорные ядра, кэш? Как сделать экономически эффективный выбор? Мы рассмотрим эти вопросы, заодно разберемся с распространенными заблуждениями, разберемся в характеристиках GPU, дадим советы, которые помогут вам сделать правильный выбор.
Эта статья призвана повысить ваш уровень понимания технологии GPU, в том числе новых графических процессоров серии Ampere от NVIDIA. Выберите свой способ чтения этого текста.
(1) Если вас не интересуют детали работы GPU, что делает GPU быстрее CPU и что уникального в новой серии NVIDIA RTX 40 Ampere, вы можете сразу перейти к диаграммам производительности, удельной производительности на единицу инвестиций и к разделу рекомендаций. Цифры стоимости/производительности составляют основу статьи, а окружающий контент объясняет детали того, из чего складывается производительность GPU.
(2) Если вас волнуют конкретные вопросы, смотрите мои ответы на самые распространенные вопросы и заблуждения в дальнейшей части статьи.
(3) Если вы хотите получить глубокое понимание того, как работают GPU, кэши и тензорные ядра, лучше всего прочитать эту статью от начала до конца. Возможно, вы захотите пропустить один или два раздела в зависимости от вашего понимания представленных тем.
Краткий обзор
Эта статья построена следующим образом. Сначала я объясню, что делает GPU таким быстрым. Я расскажу о сравнении CPU и GPU, тензорных ядрах, пропускной способности памяти и иерархии памяти GPU, а также о том, как они связаны с производительностью глубокого обучения. Эти объяснения помогут вам получить более интуитивное представление о том, как выбирать GPU. Я расскажу об уникальных особенностях новой серии GPU NVIDIA RTX 40 Ampere, на которую стоит обратить внимание при покупке GPU. Затем я дам рекомендации по выбору GPU для различных сценариев. После этого следует раздел «Вопросы и ответы», в котором собраны типичные вопросы, заданные мне в соцсетях; в этом разделе я также рассмотрю распространенные заблуждения и некоторые другие вопросы, такие как облако vs настольный ПК, проблемы охлаждения, AMD vs NVIDIA и другие.
Как работают графические процессоры?
Если вы часто используете графические процессоры, полезно понимать, как они работают. Эти знания помогут вам понять, в каких случаях GPU работает быстро или медленно. В свою очередь, вы сможете лучше понять, зачем вам вообще нужен GPU и как другие аппаратные средства могут конкурировать с ним в будущем. Вы можете пропустить этот раздел, если вам нужны только цифры производительности и аргументы, которые помогут вам решить, какой GPU купить.
Наиболее важные характеристики GPU с точки зрения скорости обработки данных для глубокого обучения
Этот раздел поможет вам сформировать более интуитивное понимание того, как следует думать о производительности глубокого обучения. Это понимание поможет вам самостоятельно оценивать существующие и будущие GPU. Раздел отсортирован по степени важности каждого компонента. Наиболее важны тензорные ядра, затем следует пропускная способность памяти GPU, иерархия кэша, и только потом количество FLOPS GPU.
Тензорные ядра
Тензорные ядра (Tensor Cores) – это крошечные ядра, которые выполняют очень эффективное умножение матриц. Поскольку самой затратной частью любой глубокой нейронной сети является матричное умножение, тензорные ядра призваны решить эту задачу. Если кратко, то они настолько мощные, что я не рекомендую использовать GPU, в которых нет тензорных ядер.
Чтобы оценить важность этих вычислительных блоков, специализированных для умножения матриц, полезно понять, как они работают. Я покажу вам на простом примере умножение матриц A*B=C, где обе матрицы имеют размер 32×32, с тензорными ядрами и без них. Это упрощенный пример, не совсем то, как должно быть написано высокопроизводительное ядро для умножения матриц, но в нем есть все основы. Программист CUDA взял бы его в качестве «черновика» и затем шаг за шагом оптимизировал бы его с помощью таких концепций, как двойная буферизация, оптимизация регистров, оптимизация загруженности, параллелизм на уровне инструкций и многих других, которые я сейчас не буду обсуждать.
Чтобы понять этот пример, необходимо разобраться в концепции тактов процессора. Если процессор работает на частоте 1 ГГц, он может совершать 109 тактов в секунду. Каждый такт представляет собой возможность сделать какое-то действие. Однако чаще всего операции занимают больше времени, чем один такт. Таким образом, по сути, мы имеем очередь, в которой следующая операция должна дождаться завершения предыдущей. Это также называется задержкой операции.
Вот некоторые важные тайминги тактов для операций. Это время может меняться от поколения к поколению GPU. Эти цифры относятся к графическим процессорам Ampere, которые имеют относительно медленный кэш.
-
Доступ к оперативной памяти (до 80 ГБ): ~380 тактов
-
Кэш L2: ~200 тактов
-
Кэш L1 или доступ к общей памяти (до 128 кб на потоковый мультипроцессор): ~34 такта
-
Слитное умножение и сложение, a*b+c (FFMA): 4 такта
-
Матричное умножение в тензорном ядре: 1 такт
Каждая операция всегда выполняется пакетом из 32 потоков. Этот пакт называется группой потоков (warp). Обычно варпы работают синхронно – потоки внутри варпа должны ждать друг друга. Все операции с памятью на GPU оптимизированы для варпов. Например, загрузка из оперативной памяти происходит с гранулярностью 32*4 байта, ровно 32 числа float, или один float для каждого потока в варпе. Мы можем иметь до 32 варпов = 1024 потока в потоковом мультипроцессоре (streaming multiprocessor, SM), GPU-эквиваленте ядра CPU. Ресурсы SM распределяются между всеми активными варпами. Это означает, что иногда мы хотим запускать меньше варпов, чтобы иметь больше регистров/ общей памяти/ ресурсов тензорных ядер на варп.
В обоих следующих примерах мы предполагаем, что у нас одинаковые вычислительные ресурсы. Для этого небольшого примера умножения матрицы 32×32 мы используем 8 SM (около 10 % от RTX 3090) и 8 варпов на один SM.
Чтобы понять, как величины тактов сочетаются с такими ресурсами, как потоки на SM и общая память на SM, мы рассмотрим примеры умножения матриц. Хотя следующий пример примерно повторяет последовательность вычислительных шагов умножения матриц как с тензорными ядрами, так и без них, обратите внимание, что это очень упрощенные примеры. Реальные случаи умножения матриц включают в себя гораздо большие тайлы общей памяти и несколько иные схемы вычислений.
Перемножение матриц без тензорных ядер
Если мы хотим выполнить матричное умножение A*B=C, где каждая матрица имеет размер 32×32, то мы прежде всего хотим загрузить данные из оперативной памяти компьютера, к которой мы многократно обращаемся, в разделяемую (общую) память GPU, поскольку ее задержка примерно в пять раз меньше (200 тактов против 34 тактов). Блок памяти в общей памяти часто называют тайлом памяти или просто тайлом. Загрузка двух матриц float чисел 32×32 в тайл общей памяти может происходить параллельно с использованием 2*32 = 64 варпов. У нас есть 8 SM с 8 варпами в каждом (итого 64), поэтому благодаря распараллеливанию нам нужно выполнить только одну последовательную загрузку из оперативной в общую память, которая занимает 200 циклов.
Чтобы выполнить умножение матриц, нам нужно загрузить вектор из 32 чисел из общей памяти A и общей памяти B и выполнить слитное умножение с накоплением (FFMA). Затем сохранить итог в регистре C. Мы делим работу так, чтобы каждый SM выполнял 8x точечных произведений (32×32) для вычисления 8 выходов C. Почему именно 8 (4 в старых алгоритмах) – это техническая особенность. Я рекомендую для понимания статью Скотта Грея о матричном умножении. Это означает, что у нас есть 8 обращений к общей памяти стоимостью 34 такта каждое и 8 операций FFMA (32 параллельно), которые стоят 4 такта каждая. Таким образом, в общей сложности затраты составляют:
200 тактов (оперативная память) + 8*34 тактов (общая память GPU) + 84 такта (FFMA) = 504 такта
Давайте рассчитаем количество тактов при использовании тензорных ядер.
Перемножение матриц с тензорными ядрами
С помощью тензорных ядер мы можем выполнить матричное умножение 4×4 за один такт. Для этого нам сначала нужно получить данные из памяти. Аналогично описанному выше, нам нужно прочитать данные из оперативной памяти (200 тактов) и сохранить их в общей памяти GPU. Чтобы выполнить умножение матрицы 32×32, нам нужно выполнить 8×8=64 операции на тензорных ядрах. Один SM имеет 8 тензорных ядер. Таким образом, с 8 SM у нас есть 64 тензорных ядра – как раз то количество, которое нам нужно! Мы можем передать данные из общей памяти на тензорные ядра с помощью 1 операции передачи данных из памяти (34 такта), а затем выполнить эти 64 параллельные операции с тензорными ядрами (1 такт). Это означает, что общая стоимость перемножения матриц на тензорных ядрах в данном случае составляет:
200 тактов (глобальная память) + 34 такта (общая память GPU) + 1 цикл (Tensor Core) = 235 тактов
Таким образом, мы значительно сокращаем стоимость умножения матрицы с 504 тактов до 235 тактов с помощью тензорных ядер. В этом упрощенном случае тензорные ядра снизили стоимость как доступа к общей памяти GPU, так и операций FFMA.
Данный пример является упрощенным, поскольку, например, обычно каждый поток должен вычислить, в какую память читать и писать, когда вы передаете данные из оперативной памяти в общую. В новых архитектурах Hooper (H100) мы дополнительно используем аппаратный ускоритель тензорной памяти (TMA) для вычисления этих индексов, что позволяет каждому потоку сосредоточиться на собственно перемножении, а не на вычислении индексов.
Умножение матриц с помощью тензорных ядер и асинхронных копий (RTX 30/RTX 40) и TMA (H100)
Графические процессоры серий RTX 30 Ampere и RTX 40 Ada дополнительно поддерживают асинхронную передачу данных между оперативной и общей памятью. В графическом процессоре H100 Hopper эта поддержка расширена за счет блока Tensor Memory Accelerator (TMA). Блок TMA объединяет асинхронные копии и вычисление индексов для чтения и записи одновременно – таким образом, каждому потоку больше не нужно вычислять, какой элемент читать следующим, и каждый поток может сосредоточиться на выполнении большего количества вычислений матричного умножения. Это выглядит следующим образом.
Блок TMA выполняет выборку данных из оперативной в общую память (200 тактов). Как только данные поступают, блок TMA асинхронно извлекает следующий блок данных из оперативной памяти. Пока это происходит, потоки загружают данные из общей памяти и выполняют матричное умножение с помощью тензорного ядра. По завершении потоки ждут, пока блок TMA завершит следующую передачу данных, и всё повторяется.
Таким образом, из-за асинхронного характера второе чтение оперативной памяти блоком TMA происходит уже в процессе обработки потоками текущего тайла общей памяти. Это означает, что второе чтение занимает всего 200 – 34 – 1 = 165 тактов.
Поскольку мы выполняем много чтений, медленным будет только первое обращение к памяти, а все остальные обращения к памяти будут частично перекрываться блоком TMA. Таким образом, в среднем мы сокращаем время на 35 тактов.
165 тактов (ожидание завершения async-копирования) + 34 такта (общая память) + 1 такт (Tensor Core) = 200 тактов
Это ускоряет умножение матриц еще на 15 %.
Из этих примеров становится понятно, почему следующий атрибут, пропускная способность памяти (memory bandwidth), так важен для GPU, оснащенных тензорными ядрами. Поскольку оперативная память – это, безусловно, самая большая стоимость такта при матричном умножении на тензорных ядрах, мы получим более быстрые GPU, если сможем уменьшить задержку чтения из оперативной памяти. Это можно сделать, либо увеличив тактовую частоту памяти (больше тактов в секунду, но также – выше тепловыделение и энергопотребление), либо увеличив количество элементов, которые могут быть переданы в один момент времени (ширина шины).
Пропускная способность памяти (Memory Bandwidth)
Выше мы убедились, что тензорные ядра очень быстры. На самом деле они настолько быстры, что большую часть времени простаивают в ожидании поступления данных из оперативной памяти. Например, во время обучения на GPT-3, в котором используются огромные матрицы – чем больше, тем лучше, – мы имеем использование TFLOPS тензорных ядер примерно на 45-65 %, что означает, что даже для больших нейронных сетей примерно 50% времени тензорные ядра простаивают.
Это означает, что при сравнении двух GPU с тензорными ядрами одним из лучших показателей производительности каждого GPU является пропускная способность его памяти. Например, пропускная способность памяти графического процессора A100 составляет 1 555 ГБ/с против 900 ГБ/с у V100. Таким образом, базовая оценка ускорения вычислений A100 по сравнению с V100 составляет 1555/900 = 1,73x.
L2 Cache / Общая память (Shared Memory) / L1 Cache / Регистры
Поскольку передача данных из оперативной памяти к тензорным ядрам является ограничивающим фактором производительности, мы используем другие составляющие GPU, которые позволяют быстрее передавать данные к тензорным ядрам. Это кэш L2, общая память, кэш L1 и количество используемых регистров. Чтобы понять, как иерархия памяти обеспечивает более быструю передачу данных, нужно понимать, как выполняется матричное умножение на GPU.
Для выполнения умножения матриц мы используем иерархию памяти GPU, которая переходит от медленной оперативной памяти к более быстрой памяти L2, к быстрой локальной общей памяти и к молниеносным регистрам. Однако чем быстрее память, тем она меньше.
Хотя логически память L2 и L1 одинаковы, кэш L2 больше, а значит, и среднее физическое расстояние, которое нужно преодолеть, чтобы получить строку кэша, больше. Вы можете представить себе кэши L1 и L2 как организованные склады, из которых вы хотите извлечь какой-либо предмет. Вы знаете, где находится этот предмет, но чтобы добраться до него, в среднем требуется больше времени для более крупного склада. В этом и заключается существенное различие между кэшами L1 и L2. Большой = медленный, маленький = быстрый.
Для умножения матриц мы можем использовать это иерархическое разделение на все меньшие и меньшие, а значит, все более быстрые куски памяти, чтобы выполнять очень быстрые матричные умножения. Для этого нам нужно разбить большое матричное умножение на более мелкие “подматричные” умножения. Эти фрагменты называются тайлами памяти, или часто для краткости просто тайлами.
Мы выполняем матричное умножение по этим меньшим тайлам в локальной общей памяти, которая является быстрой и близкой к потоковому мультипроцессору (SM) – эквиваленту ядра CPU. С тензорными ядрами мы идем на шаг дальше: мы берем каждый тайл и загружаем часть этих тайлов в тензорные ядра, к которым напрямую обращаемся через регистры. Тайлы матричной памяти в кэше L2 в 3-5 раз быстрее памяти GPU (GPU RAM), которая в ~7-10 раз быстрее оперативной, а регистры тензорных ядер в ~200 раз быстрее оперативной памяти.
Наличие больших тайлов означает, что мы можем повторно использовать больше памяти. Я подробно писал об этом в своей статье в блоге TPU vs GPU. На самом деле, вы можете видеть, что TPU имеют очень, очень, очень большие тайлы для каждого тензорного ядра. Таким образом, TPU могут повторно использовать гораздо больше памяти при каждой передаче данных из оперативной памяти, что делает их немного более эффективными при матричных умножениях, чем GPU.
Размер каждого тайла определяется тем, сколько памяти у нас есть на один потоковый мультипроцессор (SM) и сколько L2-кэша у нас есть на всех SM. Мы имеем следующие объемы общей памяти на следующих архитектурах:
-
Volta (Titan V): 128 Кб общей памяти / 6 Мб L2
-
Turing (серия RTX 20s): 96 кб общей памяти / 5,5 МБ L2
-
Ampere (серия RTX 30s): 128 кб общей памяти / 6 МБ L2
-
Ada (серия RTX 40s): 128 кб общей памяти / 72 МБ L2
Мы видим, что Ada имеет гораздо больший кэш L2, что позволяет использовать тайлы большего размера, что уменьшает обращение к оперативной памяти. Например, для большого BERT во время обучения входная и весовая матрицы любого матричного умножения умещаются в L2-кэше Ada (но не в картах других архитектур). Таким образом, данные нужно загрузить из глобальной памяти только один раз, а затем они доступны через L2-кэш, что делает матричное умножение примерно в 1,5-2 раза быстрее для архитектуры Ada. Для больших моделей увеличение скорости обучения ниже, но существуют определенные “удачные параметры”, которые могут сделать обучение некоторых моделей намного более быстрым. Работа с батчами размером более 8 также может выиграть от больших кэшей L2.
Оценка производительности глубокого обучения Ada / Hopper
Этот раздел предназначен для тех, кто хочет разобраться в технических деталях того, как я получаю оценки производительности для графических процессоров Ampere. Если вас не интересуют эти технические аспекты, можете пропустить этот раздел.
Практические оценки скорости Ada / Hopper
Предположим, у нас есть оценка для одного GPU с архитектурой типа Hopper, Ada, Ampere, Turing или Volta. Легко экстраполировать эти результаты на другие GPU той же архитектуры/серии. К счастью, NVIDIA уже провела бенчмарки A100 vs V100 vs H100 в широком спектре задач компьютерного зрения и понимания естественного языка. Но, к сожалению, NVIDIA позаботилась о том, чтобы эти цифры не были напрямую сопоставимы, используя различные размеры батчей и количество GPU, когда это возможно, в пользу результатов для GPU H100. Так что в некотором смысле цифры бенчмарка – это частично честные, частично маркетинговые цифры. В целом, можно утверждать, что использование больших объемов батчей справедливо, поскольку GPU H100/A100 имеет больше памяти. Тем не менее, чтобы непредвзято сравнивать архитектуры GPU, мы должны оценивать производительность при одинаковом объеме батча.
Чтобы получить объективную оценку, мы можем масштабировать результаты GPU для дата-центров двумя способами: (1) учесть разницу в размере батча, (2) учесть разницу в использовании 1 против 8 GPU. К счастью, мы можем найти оценку для обеих отличий в предоставленных NVIDIA данных.
Удвоение размера батча увеличивает пропускную способность в пересчете на изображение в секунду (CNNs) на 13,6%. Я проверил это для трансформеров на своем RTX Titan и, к удивлению, получил тот же результат: 13,5%. Похоже, это надежная оценка.
По мере распараллеливания сетей на все большее количество GPU мы теряем производительность из-за сетевых накладных расходов. В системе A100 8x GPU сетевые возможности лучше (NVLink 3.0), чем в системе V100 8x GPU (NVLink 2.0) – это еще один сбивающий с толку фактор. Глядя непосредственно на данные NVIDIA, мы можем обнаружить, что система с 8x A100 имеет на 5% меньшие накладные расходы, чем система с 8x V100. Это означает, что если переход от 1x A100 к 8x A100 дает ускорение, скажем, в 7 раз, то переход от 1x V100 к 8x V100 дает ускорение только 6,67 раз. Для трансформеров этот показатель составляет 7 %.
Используя эти данные, мы можем оценить ускорение для нескольких конкретных архитектур глубокого обучения на основе прямых данных, которые предоставляет NVIDIA. Tesla A100 обеспечивает следующее ускорение по сравнению с Tesla V100:
-
SE-ResNeXt101: 1,43x
-
Masked-R-CNN: 1.47x
-
Трансформер (12 слоев, машинный перевод, WMT14 en-de): 1.70x
Таким образом, цифры немного ниже теоретической оценки для компьютерного зрения. Это может быть связано с меньшей размерностью тензора, накладными расходами от операций, необходимых для подготовки умножения матрицы, таких как img2col или Fast Fourier Transform (FFT), или операциями, которые не могут полностью загрузить GPU (финальные слои часто относительно малы). Также это могут быть артефакты конкретных архитектур (сгруппированная свертка).
Практическая оценка трансформеров очень близка к теоретической. Вероятно, это связано с тем, что алгоритмы для огромных матриц очень просты. Я буду использовать эти практические оценки для расчета экономической эффективности GPU.
Возможные погрешности в оценках
Приведенные выше оценки относятся к графическим процессорам H100, A100 и V100. В прошлом NVIDIA скрывала необъявленные снижения производительности в «игровых» GPU RTX: (1) снижение использования тензорных ядер, (2) игровые вентиляторы для охлаждения, (3) отключение одноранговой передачи GPU. Возможно, в серии RTX 40 есть необъявленные снижения производительности по сравнению с полноценным Hopper H100.
На данный момент одно из таких снижений было обнаружено для графических процессоров Ampere: производительность тензорных ядер была снижена, поэтому GPU серии RTX 30 не так хороши, как карты Quadro для целей глубокого обучения. Это было сделано и для серии RTX 20, так что в этом нет ничего нового, но на этот раз это было сделано и для RTX 3090, эквивалентной карты Titan. У RTX Titan не было включено снижение производительности.
В настоящее время о снижении производительности графических процессоров Ada ничего не известно, но я буду обновлять этот пост и сообщать об этом своим подписчикам.
Преимущества и проблемы серий RTX40 и RTX 30
Новая серия NVIDIA Ampere RTX 30 имеет некоторые преимущества по сравнению с серией NVIDIA Turing RTX 20, такие как обучение разреженных сетей. Другие возможности, такие как новые типы данных, следует рассматривать скорее как облегчение использования, поскольку они обеспечивают тот же прирост производительности, что и Turing, но не требуют дополнительного программирования.
Серия Ada RTX 40 имеет еще больше преимуществ, например, тензорные ядра 8-bit Float (FP8). Серия RTX 40 также имеет схожие с RTX 30 проблемы с питанием и температурой. Проблему плавления кабелей разъемов питания в RTX 40 можно легко предотвратить, правильно подключив кабель питания.
Обучение разреженных сетей
Ampere позволяет выполнять автоматическое перемножение разреженных матриц на высоких скоростях. Как это работает? Возьмем матрицу весов и разрежем ее на части по 4 элемента в каждой. Теперь представьте, что 2 элемента из этих 4 равны нулю. На рисунке 1 показано, как это может выглядеть.
![Рис. 1: Структура, поддерживаемая функцией умножения разреженных матриц в графических процессорах Ampere. Рисунок взят из презентации Джеффа Пула на GTC 2020 по ускорению разреженности в архитектуре NVIDIA Ampere, любезно предоставленной NVIDIA. Рис. 1: Структура, поддерживаемая функцией умножения разреженных матриц в графических процессорах Ampere. Рисунок взят из презентации Джеффа Пула на GTC 2020 по ускорению разреженности в архитектуре NVIDIA Ampere, любезно предоставленной NVIDIA.](https://habrastorage.org/getpro/habr/upload_files/f87/d55/e1f/f87d55e1f390351ed05865ef9b61e5ac.jpg)
Когда вы умножаете эту разреженную матрицу весов на плотные входные данные, функция тензорного ядра для разреженных матриц в Ampere автоматически сжимает разреженную матрицу до плотного представления вдвое меньшего размера, как показано на рисунке 2. После этого сжатия тайл плотной матрицы подается в тензорное ядро, которое производит матричное умножение вдвое большего размера, чем обычно. Это позволяет добиться 2-х кратного ускорения, поскольку требования к пропускной способности при умножении матрицы из общей памяти снижаются вдвое.
![Рис. 2: Разреженная матрица сжимается до плотного представления перед выполнением матричного умножения. Рисунок взят из презентации Джеффа Пула на GTC 2020 по ускорению разреженности в архитектуре NVIDIA Ampere, любезно предоставленной NVIDIA. Рис. 2: Разреженная матрица сжимается до плотного представления перед выполнением матричного умножения. Рисунок взят из презентации Джеффа Пула на GTC 2020 по ускорению разреженности в архитектуре NVIDIA Ampere, любезно предоставленной NVIDIA.](https://habrastorage.org/getpro/habr/upload_files/c1f/8a8/b1d/c1f8a8b1dae827da3794dc348ccedbbe.jpg)
Я работал над обучением разреженных сетей и опубликовал пост в блоге о разреженном обучении. Одно из замечаний в адрес моей работы заключалось в следующем: «вы уменьшаете количество FLOPS, необходимых для работы сети, но это не дает ускорения, поскольку GPU не могут выполнять быстрое умножение разреженных матриц». Теперь, с добавлением функции умножения разреженных матриц для тензорных ядер, мой алгоритм или другие алгоритмы обучения с разреженными матрицами действительно обеспечивают ускорение до 2 раз при обучении.
![Рис. 3. Разработанный мной алгоритм обучения с разреженными весами состоит из трех этапов: (1) Определить важность каждого слоя. (2) Удаление наименее важных весов. (3) Наращивание новых весов пропорционально важности каждого слоя. Подробнее о моей работе читайте в блоге, посвященном разреженному обучению. Рис. 3. Разработанный мной алгоритм обучения с разреженными весами состоит из трех этапов: (1) Определить важность каждого слоя. (2) Удаление наименее важных весов. (3) Наращивание новых весов пропорционально важности каждого слоя. Подробнее о моей работе читайте в блоге, посвященном разреженному обучению.](https://habrastorage.org/getpro/habr/upload_files/da9/4fb/130/da94fb13011e71fe86bd1ce03614056d.jpg)
Хотя эта функция все еще является экспериментальной, и обучение разреженных сетей пока непривычно, наличие этой функции на вашем GPU означает, что вы готовы к прорыву в будущее разреженного обучения.
Вычисления с низкой точностью
В своей работе я уже показывал, что новые типы данных могут улучшить стабильность при обратном распространении с низкой точностью.
![Рис. 4. Разработанные мной 8-битные типы данных для глубокого обучения с низкой точностью. Для deep learning полезны узкоспециализированные типы данных. В моем типе данных dynamic tree используется динамический бит, указывающий на начало двоичного дерева бисекции, которое квантует диапазон [0, 0.9], а все предыдущие биты используются для экспоненты. Это позволяет динамически представлять как большие, так и маленькие числа с высокой точностью. Рис. 4. Разработанные мной 8-битные типы данных для глубокого обучения с низкой точностью. Для deep learning полезны узкоспециализированные типы данных. В моем типе данных dynamic tree используется динамический бит, указывающий на начало двоичного дерева бисекции, которое квантует диапазон [0, 0.9], а все предыдущие биты используются для экспоненты. Это позволяет динамически представлять как большие, так и маленькие числа с высокой точностью.](https://habrastorage.org/getpro/habr/upload_files/b88/96e/0a5/b8896e0a57f2f326f1902bc43ee1de9e.jpg)
В настоящее время, если вы хотите получить стабильное обратное распространение с 16-битными числами с плавающей точкой (FP16), проблема заключается в том, что обычные типы данных FP16 поддерживают только числа в диапазоне [-65 504, 65 504]. Если ваш градиент выходит за пределы этого диапазона, градиенты превращаются в NaN. Чтобы предотвратить это при обучении на FP16, мы обычно выполняем масштабирование потерь, когда перед обратным распространением умножаем потери на небольшое число, чтобы предотвратить этот “взрыв градиента”.
Формат BrainFloat 16 (BF16) использует больше битов для экспоненты, поэтому диапазон возможных чисел такой же, как и для FP32: [-3*1038, 3*1038]. У BF16 меньше точность, то есть количество значащих цифр, но точность градиента не так важна для обучения. Таким образом, BF16 делает излишним выполнение масштабирования потерь, вам не нужно беспокоиться о том, что градиент быстро раздуется. Таким образом, мы должны заметить увеличение стабильности обучения за счет использования формата BF16 при незначительной потере точности.
В итоге, обучение с точностью BF16 может быть более стабильным, чем с точностью FP16, с той же скоростью. При использовании 32-битной точности TensorFloat (TF32) вы получаете стабильность, близкую к FP32, и при этом скорость, близкую к FP16. Для использования этих типов данных можно просто заменить FP32 на TF32, а FP16 на BF16 – никаких изменений в коде не требуется!
В целом эти новые типы данных можно рассматривать как ленивые типы данных в том смысле, что вы могли бы получить все преимущества со старыми типами данных, приложив некоторые дополнительные усилия по программированию (правильное масштабирование потерь, инициализация, нормализация, использование Apex). Таким образом, эти типы данных не обеспечивают ускорения, а просто повышают удобство использования низкой точности для обучения.
Конструкции вентиляторов и проблемы с температурой
Хотя новая конструкция вентилятора серии RTX 30 отлично справляется с охлаждением GPU, с другими конструкциями вентиляторов GPU, не относящихся к серии Foundation, могут возникнуть проблемы. Если ваш GPU нагревается выше 80 C, он снижает скорость/мощность вычислений. Такой перегрев может произойти, в частности, если вы поставите несколько GPU рядом друг с другом. Решением этой проблемы является использование расширителей PCIe для создания пространства между GPU.
Разнесение графических процессоров с помощью расширителей PCIe очень эффективно для охлаждения, и мы с коллегами из Университета Вашингтона успешно используем эту схему. Выглядит не очень красиво, но зато GPU остаются холодными! Такая система работает без проблем уже 4 года. Она также может помочь, если у вас недостаточно места для установки всех GPU в слоты PCIe. Например, если вы найдете место в корпусе настольного компьютера, то можно купить стандартные RTX 4090 с шириной слота 3 и разнести их по корпусу с помощью PCIe-удлинителей. Таким образом, вы одним простым решением сможете решить проблему и пространства для установки и охлаждения 4x RTX 4090.
![Рис. 5: 4 GPU с расширителями PCIe. Это выглядит довольно беспорядочно, но очень эффективно с точки зрения охлаждения. Я использовал эту схему в течение 4 лет, и охлаждение было отличным, несмотря на то, что GPU RTX 2080 Ti Founders Edition в этом отношении довольно проблемные. Рис. 5: 4 GPU с расширителями PCIe. Это выглядит довольно беспорядочно, но очень эффективно с точки зрения охлаждения. Я использовал эту схему в течение 4 лет, и охлаждение было отличным, несмотря на то, что GPU RTX 2080 Ti Founders Edition в этом отношении довольно проблемные.](https://habrastorage.org/getpro/habr/upload_files/8ae/afd/acc/8aeafdaccf67fa64515991c1741bbb3b.jpg)
очень эффективно с точки зрения охлаждения. Я использовал эту схему в течение 4 лет, и охлаждение было отличным, несмотря на то, что GPU RTX 2080 Ti Founders Edition в этом отношении довольно проблемные.
Трехслотовая конструкция и проблемы с питанием
RTX 3090 и RTX 4090 – это трехслотовые GPU (т.е. из-за толщины займет 1 и заблокирует 2 слота), поэтому их нельзя использовать в 4x-слотах с вентиляторами по умолчанию от NVIDIA. Это вполне оправдано, поскольку TDP (общая мощность, потребляемая компонентами печатной платы, включая графический процессор) превышает 350 Вт, и его будет сложно охладить в двухслотовой конфигурации с несколькими GPU. RTX 3080 лишь немного лучше – 320 Вт TDP, и охлаждение 4x RTX 3080 также будет очень непростым.
В корпусе 4x RTX 3090 или 4x RTX 4090 также сложно обеспечить питание системы 4x 350 Вт = 1400 Вт или 4x 450 Вт = 1800 Вт. Блоки питания (БП) мощностью 1600 Вт вполне доступны, но иметь всего 200 Вт для питания процессора и материнской платы может быть недостаточно. Максимальная мощность компонентов используется только при их полной загрузке, а при глубоком обучении процессор обычно нагружен слабо. Таким образом, 1600-ваттный БП может хорошо работать с 4x RTX 3080, но для 4x RTX 3090 лучше поискать БП повышенной мощности (+1700 Вт). Некоторые из моих подписчиков добились большого успеха с блоками питания для майнинга – загляните в раздел комментариев, чтобы узнать больше об этом. Важно отметить, что не все торговые точки предлагают блоки питания мощностью выше 1600 Вт, особенно в США. Именно поэтому в США в настоящее время на рынке представлено мало стандартных настольных БП мощностью выше 1600 Вт. Если вы приобретаете БП для сервера или майнинга, обратите внимание на форм-фактор – убедитесь, что он вписывается в корпус вашего компьютера.
Ограничение мощности: Элегантное решение проблемы питания?
Существует возможность установить ограничение мощности для графических процессоров. Так, вы сможете программно установить предельную мощность RTX 3090 на 300 Вт вместо стандартных 350 Вт. В системе из 4 GPU это означает экономию 200 Вт, что может быть вполне достаточно для создания системы из 4 RTX 3090 с 1600-ваттным блоком питания. Это также помогает охлаждать графические процессоры. Таким образом, установка ограничения мощности позволяет решить две основные проблемы, связанные с установкой 4x RTX 3080 или 4x RTX 3090, – охлаждение и питание одновременно. Для установки 4x все еще нужны GPU с эффективным обдувом (стандартная конструкция вентиляторов подойдет), но это решает проблему мощности БП.
![Рис. 6: Снижение предельной мощности дает небольшой эффект охлаждения. Снижение предельной мощности RTX 2080 Ti на 50-60 Вт немного уменьшает температуру, а вентиляторы работают более тихо. Рис. 6: Снижение предельной мощности дает небольшой эффект охлаждения. Снижение предельной мощности RTX 2080 Ti на 50-60 Вт немного уменьшает температуру, а вентиляторы работают более тихо.](https://habrastorage.org/getpro/habr/upload_files/697/e76/e42/697e76e423404e1166f9a4cdcba48424.jpg)
Вы можете спросить: «Разве это не замедляет работу GPU?». Да, это так, но вопрос в том, насколько. Чтобы проверить это, я провел бенчмаркинг системы 4x RTX 2080 Ti, показанной на рисунке 5, при различных ограничениях мощности. Я оценивал время выполнения 500 мини-батчей для BERT Large (без учета слоя softmax). Я выбрал BERT Large, поскольку, по моему опыту, именно эта модель глубокого обучения больше всего нагружает GPU. Поэтому я ожидаю, что ограничение мощности приведет к наиболее сильному замедлению этой модели. Поэтому приведенные здесь значения замедления, вероятно, близки к максимальному, которого можно ожидать. Результаты показаны на рисунке 7.
![Рис. 7: Измеренное замедление при заданном ограничении мощности на RTX 2080 Ti. Измерения представляют собой среднее время обработки 500 мини-батчей BERT Large во время вывода (без учета слоя softmax). Рис. 7: Измеренное замедление при заданном ограничении мощности на RTX 2080 Ti. Измерения представляют собой среднее время обработки 500 мини-батчей BERT Large во время вывода (без учета слоя softmax).](https://habrastorage.org/getpro/habr/upload_files/621/6c4/e84/6216c4e84c9b9819178a2979c3acc88f.jpg)
RTX 2080 Ti. Измерения представляют собой среднее время обработки 500
мини-батчей BERT Large во время вывода (без учета слоя softmax).
Как мы видим, установка лимита мощности не оказывает серьезного влияния на производительность. Ограничение мощности на 50 Вт – более чем достаточно для работы с 4x RTX 3090, поскольку снижает производительность всего на 7%.
RTX 4090 и плавящиеся разъемы питания: Как предотвратить проблемы
Существует ошибочное мнение, что кабели питания RTX 4090 плавятся из-за их перегиба. Выяснилось, что такая проблема возникла лишь у 0,1 % пользователей, и из-за ошибки пользователя. Вот видео, которое показывает, что основная проблема заключается в неправильной установке кабелей.
Таким образом, использование карт RTX 4090 совершенно безопасно, если вы следуете следующим инструкциям по установке:
-
Если вы используете старый кабель или старый GPU, убедитесь, что на контактах нет мусора/пыли.
-
Используйте разъем питания и вставляйте его в гнездо до тех пор, пока не услышите щелчок – это важно.
-
Проверьте плотность прилегания, покачивая кабель питания влево-вправо. Кабель не должен свободно двигаться.
-
Осмотрите контакт с гнездом: между кабелем и гнездом не должно быть зазора.
Поддержка 8-битных операций с плавающей запятой в графических процессорах серий H100 и RTX 40
Поддержка 8-битного Float (FP8) – это огромное преимущество для графических процессоров серии RTX 40 и H100. 8-битные входные слои позволяют загружать данные для матричного умножения в два раза быстрее, хранить в два раза больше элементов матрицы в кэшах, которые в архитектуре Ada и Hopper очень велики. Теперь с тензорными ядрами FP8 вы получаете 0,66 PFLOPS вычислений для RTX 4090 – это больше FLOPS, чем у всего самого быстрого суперкомпьютера в мире в 2007 году. 4x RTX 4090 с вычислениями FP8 могут соперничать с самым быстрым суперкомпьютером в мире в 2010 году (глубокое обучение началось с 2009 года).
Основная проблема использования 8-битной точности заключается в том, что трансформеры могут стать очень нестабильными при таком малом количестве битов и рухнуть во время обучения или генерировать бессмыслицу во время вывода. Я написал статью о возникновении нестабильности в LLM, а также более доступный пост.
Основной вывод: Использование 8 бит вместо 16 делает модели очень нестабильными, но если вы сохраняете пару размерностей с высокой точностью, все работает просто отлично.
![Основные результаты моей работы по 8-битному умножению матриц для больших языковых моделей (LLM). Мы видим, что лучшая 8-битная кривая не может обеспечить хорошую производительность. Разработанный мной метод LLM.int8() может выполнять умножение матриц Int8 с теми же результатами, что и 16-битная базовая модель. Основные результаты моей работы по 8-битному умножению матриц для больших языковых моделей (LLM). Мы видим, что лучшая 8-битная кривая не может обеспечить хорошую производительность. Разработанный мной метод LLM.int8() может выполнять умножение матриц Int8 с теми же результатами, что и 16-битная базовая модель.](https://habrastorage.org/getpro/habr/upload_files/306/fe3/2c3/306fe32c3176040bdea1951498ae36d6.png)
больших языковых моделей (LLM). Мы видим, что лучшая 8-битная кривая не может обеспечить хорошую производительность. Разработанный мной метод LLM.int8() может выполнять умножение матриц
Int8 с теми же результатами, что и 16-битная базовая модель.
Но Int8 уже поддерживался в графических процессорах поколения RTX 30 / A100 / Ampere, почему же FP8 в RTX 40 – это важное обновление? Тип данных FP8 гораздо стабильнее типа данных Int8, и его легко использовать в таких функциях, как нормирование слоя или нелинейные функции, что трудно сделать с типом данных Integer. Это упростит его использование в обучении и выводе. Я думаю, что через пару месяцев это сделает обучение и работу моделей на FP8 относительно обычным делом.
Если вы хотите прочитать больше о преимуществах типов данных Float и Integer, вы можете прочитать мою недавнюю статью о законах масштабирования k-bit inference. Ниже вы можете увидеть один релевантный основной результат для типов данных Float vs Integer из этой статьи. Мы видим, что бит за битом тип данных FP4 сохраняет больше информации, чем тип данных Int4, и тем самым улучшает среднюю точность LLM.
![Законы масштабирования 4-битных выводов для Pythia Large Language Models для различных типов данных. Мы видим, что 4-битные типы данных float имеют лучшую точность по сравнению с типами данных Int4. Законы масштабирования 4-битных выводов для Pythia Large Language Models для различных типов данных. Мы видим, что 4-битные типы данных float имеют лучшую точность по сравнению с типами данных Int4.](https://habrastorage.org/getpro/habr/upload_files/25a/b0a/068/25ab0a068f09b77bb95b2d6c5eb9b8cc.png)
для различных типов данных. Мы видим, что 4-битные типы данных float
имеют лучшую точность по сравнению с типами данных Int4.
Рейтинг графических процессоров по производительности
Ниже мы видим график производительности всех GPU. Мы видим, что существует гигантский разрыв в 8-битной производительности GPU H100 и старых карт, оптимизированных под 16 бит.
![](https://habrastorage.org/getpro/habr/upload_files/f9d/b57/3fd/f9db573fdca4c4938094a0aa6aa14a33.png)
Показана относительная производительность GPU. Например, RTX 4090 имеет примерно 0,33 от производительности H100 SMX для 8-битной работы. Другими словами, H100 SMX в три раза быстрее для 8 бит по сравнению с RTX 4090.
Для этих данных я не моделировал 8-битные вычисления для старых GPU. Я сделал это потому, что 8-битные вычисления и обучение гораздо эффективнее на GPU Ada/Hopper благодаря 8-битному типу данных Float и Tensor Memory Accelerator (TMA), который избавляет от необходимости вычислять индексы чтения/записи, что особенно полезно для 8-битного матричного умножения. В Ada/Hopper также есть поддержка FP8, что делает, в частности, 8-битное обучение гораздо более эффективным.
Я не моделировал данные для 8-битного обучения, потому что для этого нужно знать латентность кэшей L1 и L2 на графических процессорах Hopper/Ada, а они неизвестны, и у меня нет доступа к таким GPU. На Hopper/Ada производительность 8-битного обучения вполне может быть в 3-4 раза выше производительности 16-битного обучения, если кэши настолько быстры, как об этом ходят слухи.
Но даже с новыми тензорными ядрами FP8 есть некоторые дополнительные проблемы, которые сложно учесть при моделировании производительности GPU. Например, тензорные ядра FP8 не поддерживают транспонированное умножение матриц, что означает, что обратное распространение требует либо отдельного транспонирования перед умножением, либо хранения в памяти двух наборов весов – транспонированного и нетранспонированного. Я использовал два набора весов, когда экспериментировал с обучением Int8 в своем проекте LLM.int8(), и это довольно сильно снижало общее ускорение. Я думаю, что с правильными алгоритмами/программным обеспечением можно добиться большего, но это показывает, что отсутствие таких функций, как транспонированное умножение матрицы для тензорных ядер, может повлиять на производительность.
На старых графических процессорах производительность выводов на Int8 близка к производительности выводов на 16-битных процессорах для моделей с параметрами менее 13B. Производительность Int8 на старых GPU имеет значение только в том случае, если у вас относительно большие модели с 175B параметров и более. Если вас интересует 8-битная производительность старых GPU, вы можете прочитать приложение D к моей статье LLM.int8(), где я провожу бенчмаркинг производительности Int8.
Производительность глубокого обучения на GPU в расчете на 1 доллар
Ниже мы видим график производительности на 1 доллар США для всех графических процессоров, отсортированных по производительности 8-битного решения задач. Как использовать этот график для поиска подходящего GPU:
-
Определите объем памяти GPU, который вам необходим (грубо: не менее 12 ГБ для генерации изображений; не менее 24 ГБ для работы с трансформерами).
-
Пока 8-битный инференс (работа) и обучение являются экспериментальными, но, думаю, в течение ближайшего полугода они станут обычными. Возможно, в это время вам придется написать дополнительный сложный код для работы с 8-битными данными. Если это не для вас, выбирайте 16-битную производительность.
-
Используя метрику, определенную в (2), найдите GPU с наибольшей относительной производительностью на 1 доллар, который имеет необходимый вам объем памяти.
Видно, что RTX 4070 Ti наиболее экономически эффективен для 8- и 16-битного инференса, а RTX 3080 остается наиболее экономически эффективным для 16-битного обучения. Хотя эти графические процессоры являются наиболее экономичными, их не рекомендуется использовать, поскольку они часто не обладают достаточным объемом памяти. Тем не менее, это могут быть идеальные карты для начала вашего путешествия в глубокое обучение. Некоторые из этих графических процессоров отлично подходят для соревнований Kaggle, где часто используют небольшие модели, поскольку для успешного участия в соревнованиях Kaggle метод работы важнее, чем размер модели.
Лучшими GPU для промышленных серверов и серверов стартапов кажутся графические процессоры A6000 Ada (не путать с A6000 Turing). Графический процессор H100 SXM также очень экономичен, имеет большой объем памяти и очень высокую производительность. Если бы я собирал небольшой кластер для компании/ лаборатории, я бы использовал 66-80% GPU A6000 и 20-33% GPU H100 SXM. Если я получу хорошее предложение на графические процессоры L40, я также выберу их вместо A6000, так что можете запросить цену и на них.
![Показана относительная производительность графических процессоров в расчете на 1 доллар США, с учетом стоимости настольного компьютера и средней цены на Amazon и eBay для каждого GPU. Кроме того, добавлена стоимость электроэнергии, потребленной в течение 5 лет при цене электроэнергии 0,175 доллара США за кВт*ч и коэффициенте использования GPU 15 %. Стоимость электроэнергии для RTX 4090 составляет около 100 долларов в год. Как читать и интерпретировать диаграмму: настольный компьютер с картами RTX 4070 Ti, которыми вы владеете в течение 5 лет, дает примерно в 2 раза больше производительности 8-битных выводов на доллар по сравнению с GPU RTX 3090. Показана относительная производительность графических процессоров в расчете на 1 доллар США, с учетом стоимости настольного компьютера и средней цены на Amazon и eBay для каждого GPU. Кроме того, добавлена стоимость электроэнергии, потребленной в течение 5 лет при цене электроэнергии 0,175 доллара США за кВт*ч и коэффициенте использования GPU 15 %. Стоимость электроэнергии для RTX 4090 составляет около 100 долларов в год. Как читать и интерпретировать диаграмму: настольный компьютер с картами RTX 4070 Ti, которыми вы владеете в течение 5 лет, дает примерно в 2 раза больше производительности 8-битных выводов на доллар по сравнению с GPU RTX 3090.](https://habrastorage.org/getpro/habr/upload_files/3f2/005/c0d/3f2005c0db690147357a0260578a1039.png)
Рекомендации по выбору GPU
Я создал блок-схему рекомендаций, которую вы можете увидеть ниже (интерактивное приложение от Nan Xiao). Хотя эта схема поможет вам в 80 % случаев, но иногда она не совсем подойдет, потому что варианты могут оказаться слишком дорогими. В таком случае попробуйте взглянуть на приведенные выше бенчмарки и выбрать наиболее экономичный GPU, который при этом будет иметь достаточно GPU-памяти для вашего случая. Вы можете оценить объем необходимой GPU-памяти, запустив свою задачу в vast.ai или Lambda Cloud. vast.ai или Lambda Cloud может также подойти, если GPU вам нужен довольно редко (раз в пару дней на несколько часов) и вам не нужно загружать и обрабатывать большой набор данных, чтобы начать работу. Однако облачные GPU обычно не лучший вариант, если вы используете свой GPU в течение нескольких месяцев с высокой частотой использования каждый день (например, по 12 часов в день). Чтобы определить, подходит ли вам облачный GPU, можно воспользоваться примером из раздела «Когда лучше использовать облако по сравнению с выделенным настольным/серверным GPU?».
![Таблица рекомендаций GPU для процессоров Ada/Hopper. Следуйте ответам на вопросы «Да/Нет», чтобы найти наиболее подходящий для вас GPU. Хотя эта таблица работает примерно в 80 % случаев, в итоге вы можете получить слишком дорогой GPU. В этом случае используйте графики соотношения цены и производительности, приведенные выше. Таблица рекомендаций GPU для процессоров Ada/Hopper. Следуйте ответам на вопросы «Да/Нет», чтобы найти наиболее подходящий для вас GPU. Хотя эта таблица работает примерно в 80 % случаев, в итоге вы можете получить слишком дорогой GPU. В этом случае используйте графики соотношения цены и производительности, приведенные выше.](https://habrastorage.org/getpro/habr/upload_files/939/fc4/57d/939fc457d727544e895ecf37e30f05d1.png)
Имеет ли смысл ждать новые модели GPU? Будущее графических процессоров
Чтобы понять, имеет ли смысл пропустить текущее поколение и купить следующее, стоит немного поговорить о том, как будут выглядеть улучшения в будущем.
Раньше можно было уменьшить размер транзисторов, чтобы повысить скорость работы процессора. Сейчас этому приходит конец. Например, если уменьшение размера SRAM увеличивало ее скорость (меньшее расстояние, более быстрый доступ к памяти), то теперь это уже не так. Текущие улучшения в SRAM больше не улучшают производительность и даже могут ухудшать её. Хотя логика, такая как тензорные ядра, становится компактнее, это не обязательно делает GPU быстрее, так как основная проблема при умножении матриц заключается в доставке данных из памяти к тензорным ядрам, что диктуется скоростью и размером оперативной памяти и GPU RAM. Скорость работы оперативной памяти GPU увеличивается, если объединить модули памяти в модули с высокой пропускной способностью (HBM3+), но они слишком дороги в производстве для потребительских приложений. Основной способ повысить скорость GPU – использовать больше мощности и лучшее охлаждение, как мы видели в сериях RTX 30s и 40s. Но долго так продолжаться не может.
Еще один путь – чиплеты, используемые в процессорах AMD. AMD опередила Intel, разработав CPU chiplets. Чиплеты – это маленькие чипы, объединенные высокоскоростной сетью на кристалле. Их можно представить как два графических процессора, которые физически расположены так близко друг к другу, что их можно считать одним большим GPU. Их дешевле производить, но сложнее объединить в один большой чип. Поэтому нужно ноу-хау и быстрая связь между чиплетами. У AMD есть большой опыт в разработке чиплетов. Следующее поколение графических процессоров AMD будет представлять собой чиплеты, в то время как NVIDIA пока не имеет публичных планов по созданию таких чипов. Это может означать, что следующее поколение GPU AMD будет лучше по соотношению цена/производительность, чем GPU NVIDIA.
Однако в настоящее время основной прирост производительности GPU дает специализированная логика. Например, аппаратные блоки асинхронного копирования в поколении Ampere (RTX 30 / A100 / RTX 40) или расширение, ускоритель тензорной памяти (TMA), снижают накладные расходы на копирование памяти из медленной оперативной памяти в быструю общую память (кэш) с помощью специализированного оборудования, поэтому каждый поток может выполнять больше вычислений. TMA также снижает накладные расходы, выполняя автоматические вычисления индексов чтения/записи, что особенно важно для 8-битных вычислений, где на тот же объем памяти приходится вдвое больше элементов по сравнению с 16-битными вычислениями. Таким образом, специализированная аппаратная логика может еще больше ускорить умножение матриц.
Низкоразрядная точность – еще один прямой путь вперед на несколько лет. В ближайшие месяцы мы увидим повсеместное внедрение 8-битных вычислений и обучения. В следующем году мы увидим широкое распространение 4-битных вычислений. В настоящее время технологии 4-битного обучения не существует, но исследования выглядят многообещающе, и я ожидаю, что первая высокопроизводительная FP4 LLM с конкурентоспособной предсказательной производительностью будет обучена через 1-2 года.
Переход к 2-битной точности для обучения в настоящее время выглядит невозможным, но это гораздо проще, чем дальнейшее уменьшение транзисторов. Так что прогресс в аппаратной части в основном зависит от программного обеспечения и алгоритмов, позволяющих использовать специализированные возможности, предлагаемые аппаратурой.
Вероятно, мы сможем продолжать улучшать комбинацию алгоритмов + аппаратное обеспечение до 2032 года, но после этого наступит конец значимых улучшений GPU (по аналогии со смартфонами). Волна улучшений производительности после 2032 года будет происходить за счет более совершенных сетевых алгоритмов и массового аппаратного обеспечения. Неясно, будут ли бытовые GPU актуальны на данный момент. Возможно, RTX 9090 понадобится вам для запуска Super HyperStableDiffusion Ultra Plus 9000 Extra или OpenChatGPT 5.0, но может случиться и так, что какая-нибудь компания предложит высококачественный API, который будет дешевле, чем стоимость электроэнергии для RTX 9090, и вы захотите использовать ноутбук + API для генерации изображений и других задач.
Думаю, что инвестиции в 8-битный GPU в целом будут очень надежным вложением на ближайшие 9 лет. Улучшения в 4- и 2-битных процессорах, скорее всего, будут незначительными, а другие функции, такие как Sort Cores, станут актуальными только тогда, когда можно будет эффективно использовать умножение разреженных матриц. Возможно, через 2-3 года мы увидим какие-то другие улучшения, которые войдут в следующий GPU через 4 года, но если мы будем продолжать полагаться на матричное умножение, то мы можем проиграть. Таким образом, инвестиции в новые GPU станут более долгосрочными.
Вопросы, ответы и заблуждения
Нужен ли мне PCIe 4.0 или PCIe 5.0?
В целом, нет. PCIe 5.0 или 4.0 отлично подходит для кластера GPU, например, если у вас машина с 8-ю GPU, но в остальном они не дают особых преимуществ. Они позволяют лучше распараллеливать данные и немного ускоряют передачу данных. Передача данных не является узким местом в любом приложении. В компьютерном зрении в конвейере передачи данных узким местом может быть хранилище данных, но не передача данных по PCIe от CPU к GPU. Поэтому для большинства людей нет никаких реальных причин для установки PCIe 5.0 или 4.0. Выгода будет заключаться в улучшении распараллеливания на 1-7 % при установке 4 GPU.
Нужны ли мне 8 или 16 линий PCIe?
Как и в случае с PCIe 4.0 – в целом, нет. Линии PCIe нужны для распараллеливания и быстрой передачи данных, которые редко бывают узким местом. Работа GPU на 4x линиях – это нормально, особенно если у вас всего 2 GPU. Для установки 4 GPU я бы предпочел 8x линий на GPU, но работа на 4x линиях, вероятно, приведет к снижению производительности примерно на 5-10 %, если вы распараллелите все 4 GPU.
Как разместить 4x RTX 4090 или 3090, если они занимают по 3 слота PCIe?
Вам нужно приобрести один из вариантов с двумя слотами, либо попробовать распределить их с помощью PCIe-расширителей. Помимо места, вам также следует сразу подумать об охлаждении и подходящем блоке питания.
Расширители PCIe также могут решить проблемы с пространством и охлаждением, но вам нужно убедиться, что в вашем корпусе достаточно места для размещения графических процессоров. Убедитесь, что ваши расширители PCIe достаточно длинные!
Как охладить 4x RTX 3090 или 4x RTX 3080?
См. предыдущий раздел.
Можно ли использовать несколько GPU разных типов?
Да, можно! Но вы не сможете эффективно распараллелить GPU разных типов, поскольку часто будете работать на скорости самого медленного GPU (данные и полностью шардированный параллелизм). Таким образом, разные GPU прекрасно работают, но распараллеливание между ними будет неэффективным, поскольку самый быстрый GPU будет ждать, пока самый медленный GPU догонит его в точке синхронизации (обычно это касается обновления градиента).
Что такое NVLink и полезен ли он?
В целом NVLink не принесет пользы. NVLink – это высокоскоростное соединение между графическими процессорами. Он полезен, если у вас есть кластер GPU со 128 GPU. В противном случае он не даст почти никаких преимуществ по сравнению со стандартными интерфейсами PCIe.
У меня не хватает денег даже на самые дешевые GPU, которые вы рекомендуете. Что делать?
Покупайте подержанные графические процессоры. Вы можете купить небольшой дешевый GPU для прототипирования и тестирования, а затем перенести полноценные эксперименты в облако, например vast.ai или Lambda Cloud. Это может быть выгодно, если вы только время от времени тренируете, настраиваете и работаете на больших моделях, а больше времени тратите на создание прототипов на маленьких моделях.
Каков углеродный след графических процессоров? Как использовать графические процессоры, не загрязняя окружающую среду?
Я создал углеродный калькулятор для расчета углеродного следа научной деятельности ( выбросы углекислого газа от перелетов на конференции + время работы GPU). Калькулятор также можно использовать для расчета углеродного следа чистого GPU. Вы увидите, что GPU производят гораздо, гораздо больше углекислого газа, чем международные перелеты. Поэтому, если вы не хотите получить слишком большой углеродный след, вам следует убедиться, что у вас есть экологически чистый источник энергии. Если ни один поставщик электроэнергии в нашем регионе не предоставляет «зеленую» энергию, лучший способ – купить углеродные квоты. Многие люди скептически относятся к углеродным квотам. Работают ли они? Не являются ли они жульничеством?
Я считаю, что скептицизм в данном случае только вредит, потому что ничего не делать было бы вреднее, чем рисковать вероятностью быть обманутым. Если вы опасаетесь мошенничества, просто инвестируйте в портфель компенсаций, чтобы свести риск к минимуму.
Около десяти лет назад я работал над проектом, в рамках которого создавались углеродные квоты. Углеродные квоты были получены путем сжигания утечек метана из шахт в Китае. Чиновники ООН отслеживали этот процесс и требовали предоставления точных цифровых данных и физических проверок места реализации проекта. В этом случае углеродные квоты, которые были получены, были весьма достоверными. Я полагаю, что многие другие проекты имеют подобные стандарты качества.
Как распараллеливать на двух машинах?
Если вы хотите подстраховаться, вам следует приобрести сетевые карты с пропускной способностью не менее 50 Гбит/с, чтобы получить прирост скорости, если вы хотите распараллелить работу на разных машинах. Я рекомендую иметь как минимум EDR Infiniband, то есть сетевую карту с пропускной способностью не менее 50 Гбит/с. Две карты EDR с кабелем стоят около 500 долларов на eBay.
В некоторых случаях можно обойтись и 10 Гбит/с Ethernet, но это обычно касается только специальных сетей (некоторые сверточные сети) или если вы используете определенные алгоритмы (Microsoft DeepSpeed).
Действительно ли функции умножения разреженных матриц подходят для разреженных матриц в целом?
Это не так. Поскольку в разреженной матрице на каждые 4 элемента должно приходиться 2 элемента с нулевым значением, разреженные матрицы должны быть достаточно структурированными. Может быть, стоит немного скорректировать алгоритм, который предполагает объединение 4 значений в сжатое представление из 2 значений, но это также означает, что точное перемножение произвольных разреженных матриц невозможно на графических процессорах Ampere.
Нужен ли мне процессор Intel для работы с несколькими GPU?
Я не рекомендую процессоры Intel, если только вы не используете их в соревнованиях Kaggle (тяжелая линейная алгебра на CPU). Но даже для соревнований Kaggle процессоры AMD все равно отлично подходят. Процессоры AMD дешевле и лучше, чем процессоры Intel, в целом для глубокого обучения. Для системы, построенной на 4x GPU, я бы выбрал процессор Threadripper. В нашем университете мы построили десятки систем на Threadripper, и все они отлично работают – пока никаких нареканий. Для систем с 8x GPU я бы обычно выбирал CPU, с которыми у вашего поставщика есть опыт работы. Надежность CPU и PCIe/систем в системах 8x важнее, чем производительность или экономическая эффективность.
Имеет ли значение конструкция корпуса компьютера для охлаждения GPU?
Нет. Графические процессоры обычно отлично охлаждаются, если между ними есть хотя бы небольшой зазор. Конструкция корпуса даст вам 1-3 C меньшей температуры, пространство между GPU – 10-30 C. В итоге, если у вас есть пространство между GPU, охлаждение не имеет значения. Если пространства между GPU нет, вам понадобится правильный конструктив кулера (вентилятора) или другое решение (водяное охлаждение, расширители PCIe), но в любом случае конструкция корпуса и корпусные вентиляторы не имеют значения.
Смогут ли AMD GPU + ROCm когда-нибудь догнать NVIDIA GPU + CUDA?
Не в ближайшие 1-2 года. Это тройная проблема: тензорные ядра, программное обеспечение и сообщество.
Графические процессоры AMD великолепны с точки зрения чистого кремния: отличная производительность FP16, большая пропускная способность памяти. Однако отсутствие тензорных ядер или их эквивалентов делает их производительность в глубоком обучении низкой по сравнению с GPU NVIDIA. Математика с низкой точностью не подходит. Без этой аппаратной функции GPU AMD никогда не будут конкурентоспособными. По слухам, некая карта для центров обработки данных с эквивалентом Tensor Core запланирована на 2020 год, но с тех пор никаких новых данных не появилось. Наличие карт для центров обработки данных с эквивалентом Tensor Core также означает, что немногие смогут позволить себе такие GPU AMD, что даст NVIDIA конкурентное преимущество.
Допустим, AMD представит аппаратное обеспечение, подобное Tensor Core, в будущем. Тогда многие скажут: «Но для GPU AMD не существует программного обеспечения! Как же мне их использовать?». Это по большей части заблуждение. Программное обеспечение AMD через ROCm прошло долгий путь, а поддержка через PyTorch превосходна. Хотя я видел не так много отчетов об опыте использования AMD GPU + PyTorch, все программные функции интегрированы. Похоже, что если вы выберете любую сеть, вы будете прекрасно работать с ней на графических процессорах AMD. Так что здесь AMD проделала большой путь, и этот вопрос более или менее решен.
Однако если вы решите проблему программного обеспечения и отсутствия тензорных ядер, у AMD все равно останется проблема: отсутствие сообщества. Если у вас возникла проблема с графическими процессорами NVIDIA, вы можете погуглить и найти решение. Это укрепляет доверие к графическим процессорам NVIDIA. У вас есть инфраструктура, которая делает использование NVIDIA GPU простым (любой фреймворк глубокого обучения работает, любая научная проблема хорошо поддерживается). У вас есть хаки и трюки, которые делают использование NVIDIA GPU легким (например, apex). Экспертов по NVIDIA GPU и программированию можно встретить на каждом углу, в то время как экспертов по AMD GPU я знал гораздо меньше.
В плане сообщества AMD – это как Julia против Python. У Julia большой потенциал, и многие скажут, и вполне справедливо, что это лучший язык программирования для научных вычислений. Тем не менее, Julia почти не используется по сравнению с Python. Это происходит потому, что сообщество Python очень сильно. Numpy, SciPy, Pandas – мощные программные пакеты, вокруг которых собирается большое количество людей. Это очень похоже на проблему NVIDIA vs AMD.
Таким образом, скорее всего, AMD не сможет догнать NVIDIA до тех пор, пока не будет представлен эквивалент Tensor Core (1/2-1 год?) и не будет создано сильное сообщество вокруг ROCm (2 года?). AMD всегда будет отвоевывать часть доли рынка в определенных подгруппах (например, криптовалютный майнинг, центры обработки данных). Тем не менее, в области глубокого обучения NVIDIA, скорее всего, сохранит свою монополию еще как минимум пару лет.
Когда лучше использовать облако, а не выделенный компьютер/сервер с GPU?
Общее правило: если вы планируете заниматься глубоким обучением дольше года, дешевле приобрести настольный GPU. В противном случае предпочтительнее использовать облачные ресурсы, если только вы не обладаете обширными навыками работы с облачными вычислениями и не хотите получить преимущества от масштабирования количества GPU по своему усмотрению.
Цифры в следующих абзацах могут меняться, но они служат в качестве сценария, который поможет вам понять приблизительные затраты. Вы можете использовать аналогичную математику, чтобы определить, является ли облачный GPU лучшим решением для вас.
Точный момент времени, когда облачный GPU окажется дороже настольного, сильно зависит от используемого сервиса, и лучше всего посчитать самостоятельно. Ниже я привожу пример расчета для экземпляра AWS V100 spot с 1x V100 и сравниваю его со стоимостью настольного компьютера с одним RTX 3090 (аналогичная производительность). Настольный компьютер с RTX 3090 стоит 2200 долларов (2 CPU + RTX 3090). Кроме того, если вы живете в США, вам придется заплатить за электричество еще 0,12 доллара за кВт*ч. Это сравнимо с 2,14 доллара в час для инстанса AWS по требованию.
При 15-процентном использовании в год настольный компьютер потребляет:
(350 Вт (GPU) + 100 Вт (CPU))0,15 (уровень загрузки) * 24 часа * 365 дней = 591 кВтч в год.
Таким образом, 591 кВт*ч электроэнергии в год – это дополнительные $71.
Точка безубыточности для настольного компьютера по сравнению с облачным экземпляром при 15-процентном использовании (вы используете облачный экземпляр 15 % времени в течение дня) составит около 300 дней (2 311 долл. против 2 270 долл.):
$2,14/ч * 0,15 (использование) * 24 часа * 300 дней = $2,311.
Таким образом, если вы рассчитываете запускать модели глубокого обучения через 300 дней, лучше купить настольный компьютер, а не использовать инстансы AWS.
Вы можете провести аналогичные расчеты для любого облачного сервиса, чтобы принять решение о выборе облачного сервиса или настольного компьютера.
Обычно используются следующие коэффициенты использования:
-
Персональный компьютер студента: < 15%
-
Кластер GPU для студентов: > 35%
-
Исследовательский кластер в рамках всей компании: > 60%
В целом, уровень использования ниже для профессий, где обдумывание передовых идей важнее разработки практических продуктов. В некоторых областях показатели использования низкие (исследования интерпретируемости), а в других – гораздо выше (машинный перевод, языковое моделирование). В целом, использование персональных машин почти всегда переоценивается. Как правило, большинство персональных систем имеют коэффициент использования в пределах 5-10 %. Именно поэтому я настоятельно рекомендую использовать кластеры GPU для исследовательских групп и компаний вместо отдельных настольных GPU-машин.
Благодарности
Я благодарю Suhail за то, что он сообщил мне об устаревших ценах на графические процессоры H100, Gjorgji Kjosev за указание на проблемы со шрифтами, Anonymous за указание на то, что блок TMA не существует на GPU Ada, Scott Gray за указание на то, что тензорные ядра FP8 не имеют транспонированного матричного умножения, а также пользователей reddit и HackerNews за указание на многие другие улучшения.
За прошлые обновления этой записи я хочу поблагодарить Мэта Келси (Mat Kelcey) за помощь в отладке и тестировании пользовательского кода для GTX 970; Сандера Дилемана (Sander Dieleman) за то, что он указал мне на недостатки моего совета по памяти GPU для конволюционных сетей; Ханнеса Бретшнайдера (Hannes Bretschneider) за указание на проблемы с зависимостью программного обеспечения для GTX 580; и Оливера Гризеля (Oliver Griesel) за указание на решения для ноутбуков для AWS-инстансов. Я хочу поблагодарить Брэда Немира за предоставленный мне RTX Titan для бенчмарков. Я хочу поблагодарить Агрина Хилмкила, Ари Хольцмана, Габриэля Илхарко и Нам Фо за их отличные отзывы о предыдущей версии этой статьи.