Низкая задержка и высокая пропускная способность DeepSeek
Развертывание на GPU повышает производительность MoE-моделей
В большинстве систем задержка (latency) и пропускная способность часто являются конфликтующими целями, требующими компромиссов при проектировании и развертывании. Например, в плотных больших языковых моделях увеличение размера пакета (batch size) может улучшить пропускную способность, но также увеличивает задержку; увеличение тензорного параллелизма внутри одного узла может сократить задержку, но уменьшает количество реплик, что приводит к снижению пропускной способности.
Модели Mixture of Experts (MoE), такие как DeepSeek-V3/R1, недавно продемонстрировали отличные возможности и операционную эффективность. Например, модель DeepSeek-V3/R1 имеет в общей сложности 671 млрд параметров, но каждый токен использует только 37 млрд параметров во время вывода. Эта архитектура модели представляет как проблемы, так и возможности для систем вывода.
В данной статье показано, что, вопреки традиционным системам, модели MoE, такие как DeepSeek-V3/R1, могут одновременно достигать более высокой пропускной способности и меньшей задержки при использовании большего количества графических процессоров в многоузловых развертываниях в большинстве сценариев.
Архитектуры развертывания
Из-за большого количества малых экспертов, имеющихся в модели, развертывания должны быть распределены по нескольким устройствам. Мы рассмотрели как одноузловые развертывания на одном узле с 8xH200 GPU, так и многоузловые развертывания на 8xH100 GPU.
Обе архитектуры развертывания используют параллелизм данных, управляемый с помощью нашего внутреннего планировщика запросов. Реализация параллелизма данных включает запуск нескольких экземпляров движка вывода, каждый из которых работает независимо для обслуживания и поддержания запросов. Планировщик запросов, который взаимодействует с движком через GRPC, отвечает за распределение запросов как можно более равномерно, одновременно способствуя повторному использованию KV-кэша, отправляя запросы с частично совпадающим префиксом на серверы, содержащие кэш. Экземпляры движка не охватывают несколько узлов. Они могут опционально использовать тензорный параллелизм для шардирования внимания между несколькими устройствами. Экземпляры соединены друг с другом через NVLink в случае одноузловой конфигурации или InfiniBand для многоузлового случая, выполняя диспетчеризацию и сбор экспертов.
Одноузловая конфигурация развертывания обеспечивает превосходную задержку при малых размерах пакетов; однако производительность быстро снижается в условиях повышенной нагрузки.
Для развертывания движка обслуживания мы запускаем один под на узел, размещая несколько экземпляров движка. PyTorch отвечает за настройку распределенного взаимодействия и согласование инициализации NVSHMEM. Для связи мы полагаемся на пользовательские CUDA-ядра, описанные в более ранней записи блога. Реализация двух развертываний практически идентична, причем модель выбирает правильные ядра для использования на основе фабрики, реализующей экспертный параллелизм.
Методы распараллеливания
Прежде чем погрузиться в наши сравнения производительности, важно понять ключевые стратегии распараллеливания, которые делают возможным развертывание массивных MoE-моделей, таких как DeepSeek-V3/R1.
Тензорный параллелизм
При выводе LLM тензорный параллелизм (TP) обычно используется для уменьшения использования памяти и вычислений на GPU, тем самым снижая задержку. Как правило, мы можем шардировать Linear Projections в слоях внимания и MLP вдоль измерений строк или столбцов и шардировать операции внимания вдоль измерения головы внимания.
При использовании TP в архитектуре Llama-3 нет дублирующихся вычислений для операций Linear Projection и внимания между GPU, что является идеальным методом шардирования. Однако в моделях DeepSeek-V3/R1 TP не может этого достичь.
В моделях DeepSeek-V3/R1 используется Multi-Latent Attention (MLA). Слой MLA сначала использует Linear Projection kv_a_proj для вычисления латентного вектора, затем использует еще одну Linear Projection kv_b_proj для преобразования его в пространство каждой головы внимания. Поскольку все головы внимания разделяют один и тот же латентный вектор, TP не может шардировать латентный вектор, поэтому все TP-ранги должны реплицировать параметры и вычисления kv_a_proj и kv_b_proj. Аналогично, поскольку MLA хранит латентный вектор в KV-кэше, каждый TP-ранг хранит идентичную копию KV-кэша.
Несмотря на некоторое дублирование в MLA, тензорный параллелизм все еще обеспечивает частичное снижение вычислительных требований, что делает его ценным для сценариев, требующих высокой скорости вывода.
Экспертный параллелизм
Модели DeepSeek-V3/R1 заменяют слои MLP слоями MoE. Слой MoE имеет 256 маршрутизируемых экспертов и одного общего эксперта. Каждый токен отправляется 8 различным маршрутизируемым экспертам для вычисления, а результаты суммируются с весами. Каждый токен также вычисляется у общего эксперта, и результат добавляется к результату от маршрутизируемых экспертов.
Экспертный параллелизм (EP) служит типичным подходом к шардированию для слоев MoE, где каждый GPU управляет 256 / EP маршрутизируемыми экспертами, сохраняя при этом копию общего эксперта. По сравнению с TP преимущество EP заключается в том, что он может распределять вычисления между большим количеством GPU, уменьшая вычислительные затраты и использование памяти на GPU.
Перед выполнением экспертных вычислений все GPU должны выполнить взаимодействие AllToAll, чтобы отправить токены на GPU, где расположены соответствующие эксперты; после экспертных вычислений требуется еще одно взаимодействие AllToAll, чтобы собрать результаты вычислений с различных GPU и выполнить взвешенное суммирование. Мы реализовали оптимизированную версию этих двух ядер взаимодействия AllToAll, Dispatch и Combine, используя NVSHMEM. В нашем предыдущем блоге мы подробно описали реализацию, и наши ядра были открыты на GitHub.
Параллелизм данных
С помощью EP мы можем распределить вычисления MoE между 128 или даже большим количеством GPU. Однако вычисления MLA не могут быть разделены с помощью EP. В этот момент мы можем внедрить параллелизм данных (DP). Каждая группа DP имеет полную копию слоя MLA. Каждая группа DP принимает разные входные данные и выполняет вычисления слоя MLA независимо.
DP и TP слоя MLA могут быть объединены, при этом одна группа DP разбивается на несколько рангов TP. EP слоя MoE может быть объединен с DP/TP слоя MLA. EP = DP * TP. Например, на 16 машинах конфигурация EP128 DP32 TP4 означает распределение маршрутизируемых экспертов по 128 GPU, где каждые 4 GPU образуют группу DP, всего 32 независимых группы DP.
Одноузловое против многоузлового
Параметры DeepSeek объемом 671 млрд превышают емкость памяти одной машины с 8 GPU H100 (80 ГБ * 8), но одна машина с 8 GPU H200 может полностью вместить всю модель (141 ГБ * 8). При использовании конфигурации EP8 DP8 TP1 модель использует около 100 ГБ памяти на GPU, оставляя примерно 40 ГБ для KV-кэша и других промежуточных результатов. Один токен занимает 70 272 байта KV-кэша. Если предположить, что каждый запрос имеет 5000 токенов, каждый GPU может вместить примерно 100 запросов.
Мы хотели понять различия в производительности между одноузловыми и многоузловыми развертываниями при различных конфигурациях. Мы использовали одну машину H200 для одноузлового развертывания и до 16 машин H100 для многоузловых развертываний. Для каждой среды развертывания мы использовали комбинации TP 1, 2, 4, 8 и размеры пакетов на GPU 1, 2, 4, 8, 16, 32, 64, 128. Мы предположили, что каждый запрос имеет длину KV-кэша 5000 токенов. Мы также предположили, что Multi-Token Prediction (MTP) предсказывает 1 дополнительный токен (т.е. длина запроса каждого запроса равна 2), и консервативно предположили коэффициент принятия 60%. На рисунке ниже показана пропускная способность и скорость вывода для различных конфигураций.
Горизонтальная ось представляет скорость вывода на запрос в токенах/с. Вертикальная ось использует логарифмическую шкалу для отображения пропускной способности на машину в токенах/с. Мы отметили границу Парето для каждой конфигурации EP линиями разного цвета.
В сценариях с экстремально высокими требованиями к скорости вывода использование одноузлового EP8 DP1 TP8 с размером пакета 1 может достичь скорости вывода, превышающей 100 токенов/с, но пропускная способность чрезвычайно низка, эквивалентна скорости вывода. В этом сценарии весь пакет имеет только 2 токена, которые могут быть отправлены максимум на 2*8=16 экспертов, активируя в общей сложности максимум 57 млрд параметров.
В диапазоне скорости вывода 80-40 токенов/с по мере увеличения пропускной способности скорость вывода значительно снижается. Напротив, EP128 имеет примерно в 5 раз более высокую пропускную способность, чем одноузловое развертывание при той же скорости вывода.
Это явление можно объяснить, изучив поведение одноузловых развертываний: увеличение размера пакета напрямую коррелирует с увеличением количества активированных экспертов. Когда размер пакета равен 1, среднее количество активированных экспертов на GPU составляет 2 * 8 / 8 = 2. Когда пакет достаточно велик, активируются все эксперты, что означает, что каждый GPU активирует 256 / 8 = 32 эксперта. Активация большего количества экспертов означает, что GPU должен считывать больше параметров из памяти, что значительно увеличивает нагрузку на пропускную способность памяти. Поскольку фаза декодирования больших языковых моделей уже ограничена пропускной способностью памяти, а не производительностью вычислений, увеличение размера пакета при одноузловом развертывании значительно снижает скорость вывода.
Сравнение четырех конфигураций многоузлового развертывания (EP16, EP32, EP64 и EP128) показывает, что более высокие значения EP сдвигают границу Парето в сторону одновременного улучшения пропускной способности и скорости вывода.
Использование более высокого значения EP означает, что каждому GPU выделяется меньше экспертов. Например, EP128 означает, что каждый GPU отвечает за 256 / 128 = 2 эксперта, поэтому нагрузка на пропускную способность памяти значительно снижается. Другими словами, используя большее значение EP, мы фактически получаем больше пропускной способности памяти. Когда размер пакета на GPU менее 64, увеличение размера пакета не оказывает существенного влияния на скорость вычислений экспертов, поскольку увеличение количества входных данных не приводит к существенному увеличению нагрузки на пропускную способность памяти. Поэтому мы наблюдаем, что при использовании EP128 увеличение размера пакета не влияет на скорость вывода так значительно.
Интересно, что при больших размерах пакетов (64 запроса на GPU) мы наблюдали новое явление: пропускная способность одноузлового развертывания немного выше, чем у многоузлового. Частично это объясняется тем, что внутриузловой NVLink имеет более высокую пропускную способность, чем межузловой InfiniBand. Другая часть связана с ограничениями в нашей реализации. Мы проанализируем это явление более подробно позже.
Из-за ограничений емкости памяти конфигурация EP8 DP8 TP1 не может достичь размера пакета 128 на GPU, поэтому многоузловое развертывание остается лучшим выбором в сценариях, требующих более высокой пропускной способности.
Наложение вычислений и взаимодействия
Как кратко представлено выше в отношении экспертного параллелизма, GPU простаивают во время взаимодействия слоя MoE. Чтобы сократить потери и снизить задержку, нам нужно найти независимые от данных вычислительные задачи, чтобы заполнить это время простоя.
Верхняя часть рисунка выше показывает поток вычислений одного слоя. Вычисления MoE зависят от Dispatch, а вычисления следующего слоя зависят от результата Combine.
Мы размещаем общего эксперта на каждом GPU. Таким образом, вычисления общего эксперта не требуют взаимодействия AllToAll. Следовательно, мы можем выполнять вычисления общего эксперта сразу после Dispatch Send, а затем ждать завершения Dispatch Recv. Мы называем эту схему перекрытия «Dispatch Overlap».
Dispatch Overlap предлагает простую реализацию и широкую применимость. Этот метод скрывает время вычислений общего эксперта для всех размеров EP и размеров пакетов.
Чтобы еще больше увеличить перекрытие вычислений и взаимодействия, мы использовали микропакетирование, упомянутое в техническом отчете DeepSeek, чтобы разорвать зависимость от данных. Как показано в нижней части рисунка, мы разделили вычисления одного слоя Transformer на 5 этапов:
Этап 1: InputNorm, QKVProj, AppendKV, BMM
Этап 2: BMM, Attn, OProj, PostNorm, Gate
Этап 3: Dispatch Send, Shared Expert
Этап 4: Dispatch Recv, MoE, Combine Send
Этап 5: Combine Recv
В первых 3 слоях Dense Transformer мы используем весь пакет. В последующих 58 слоях MoE Transformer мы равномерно делим пакет на два микропакета. Два микропакета выполняются попеременно, со смещением в 3 этапа. Поскольку между этими двумя микропакетами нет зависимости от данных, мы можем переключиться на вычисления другого микропакета после Dispatch Send и после Combine Send.
Анализ задержки
Далее мы сравним эффекты перекрытия с помощью эксперимента, а также сравним различия в производительности между одноузловым развертыванием EP8 и многоузловым развертыванием EP128. Для удобства сравнения мы использовали GPU H100 для следующего эксперимента. Мы использовали TP1, размер пакета 128 на GPU, длину запроса 2 на запрос и длину KV-кэша 5000.
Рисунок выше показывает общее время, затраченное на один слой MoE Transformer, и долю задержки различных типов ядер. За исключением Dispatch, Combine и GroupGEMM, время выполнения других ядер должно быть одинаковым в сериях EP8, EP128 NoOverlap и EP128 DispatchOverlap, поскольку размер пакета одинаков.
Перекрытие
Давайте сначала сравним эффекты трех методов перекрытия. NoOverlap занял всего 2667 мкс, DispatchOverlap — 2651 мкс, сэкономив 16 мкс или всего 0,6%. MicroBatch показал очень значительное улучшение, заняв 1896 мкс, ускорение на 29%. Время Dispatch и Combine было значительно сокращено. Dispatch уменьшился с 593 мкс до 367 мкс, а Combine — с 1012 мкс до 237 мкс.
Обратите внимание, что для вычислительных ядер разбиение пакета размера 128 на два пакета размера 64 увеличивает общее время выполнения. Поэтому, хотя время, затраченное на взаимодействие, сократилось на 1001 мкс, общее время сократилось только на 771 мкс. Мы объясним причину, используя модель Roofline в следующем разделе.
По этой причине микропакетирование не всегда улучшает производительность.
Рисунок выше показывает улучшение производительности Microbatch по сравнению с DispatchOverlap для размеров пакетов 4-128. Когда размер пакета менее 32, Microbatch снижает производительность на 5%-40%. Когда размер пакета больше или равен 32, Microbatch может улучшить производительность на 10%-35%.
EP8 против EP128
Вернемся к предыдущему рисунку и сравним EP8 и EP128 Microbatch. EP8 занял в общей сложности 1802 мкс, что немного меньше, чем 1896 мкс у EP128. Помимо увеличенного времени выполнения ядра, вызванного Microbatch, упомянутым выше, основные различия заключаются в GroupGEMM, используемом для вычислений MoE, и двух ядрах взаимодействия, Dispatch и Combine.
GroupGEMM у EP8 занял 555 мкс, тогда как GroupGEMM у EP128 занял 270 мкс, сократившись вдвое. Это главное преимущество многоузлового развертывания.
К сожалению, время, затраченное на взаимодействие, увеличилось на 213 мкс, что значительно компенсировало преимущество GroupGEMM. В отдельных тестах производительности наших ядер взаимодействия мы обнаружили, что они могут достичь только половины пропускной способности Infiniband. Мы продолжим оптимизировать наши ядра взаимодействия.
Еще одно ядро, которое значительно отстает, — это GEMM. Microbatch увеличил GEMM на 95 мкс. Мы проанализируем GEMM более глубоко в разделе Roofline ниже. Мы считаем, что текущая реализация GEMM еще не достигла оптимальной производительности.
Roofline
Модель Roofline — хороший инструмент для анализа производительности ядра. Ее горизонтальная ось — арифметическая интенсивность, отношение FLOP к байтам ввода-вывода памяти. Значение горизонтальной оси можно рассчитать непосредственно из семантики ядра. Вертикальная ось представляет достигнутую производительность, рассчитываемую путем деления FLOP на задержку теста.
Теоретический верхний предел производительности ядра напрямую определяется спецификациями GPU. Пиковая производительность FP8 H100 составляет 1979 TFLOP/s, что представлено как горизонтальная линия в модели Roofline. Пропускная способность памяти H100 составляет 3,35 ТБ/с, что представлено как наклон линии, проходящей через начало координат. Две линии дают пределы производительности для ядер, ограниченных вычислениями и памятью, соответственно.
Ниже мы обсуждаем производительность ядер GroupGEMM и GEMM.
GroupGEMM
Ядро GroupGEMM в MoE выполняет следующие вычисления: всего существует g групп, i-я группа имеет m_i токенов, выполняя умножение матриц [m_i, k] x [k, n] -> [m_i, n]. При тестировании производительности мы предполагаем, что количество токенов в каждой группе одинаково, обозначено как m_i = m. Тогда количество FLOP для GroupGEMM равно 2 * g * m * k * n, а байты ввода-вывода памяти — g * (m * k + n * k + m * n).
В модели DeepSeek-V3/R1 имеется 256 экспертов, и каждый токен отправляется 8 экспертам для вычисления. Предполагая размер пакета 128, длину запроса 2, используя конфигурацию EP128 DP128, среднее количество токенов, полученных каждым экспертом (т.е. m), составляет 128 * 2 * 8 * 128 / 256 = 1024. Аналогично, мы можем рассчитать m для других конфигураций и размеров пакетов.
Мы использовали реализацию GroupGEMM от DeepGEMM для тестирования производительности. Тестовые точки охватывали комбинации конфигураций EP8, EP16, EP32, EP64, EP128 с TP1 и размерами пакетов 1-128.
Рисунок выше показывает модель Roofline для GroupGEMM при различных конфигурациях EP. Разным EP соответствует разное количество групп. Рисунок иллюстрирует почти перекрывающиеся линии производительности, указывая на то, что производительность GroupGEMM преимущественно определяется общим количеством токенов (представлено как g * m).
Звездочки отмечают точки данных, соответствующие размеру пакета 128 на GPU для каждой конфигурации EP. Сравнивая эти отмеченные точки данных, мы видим, что по мере увеличения EP (и синхронного увеличения DP) количество токенов на эксперта m также увеличивается. При EP8 m=128, тогда как при EP128 m=2048.
По мере увеличения m арифметическая интенсивность также увеличивается. В большинстве конфигураций GroupGEMM ограничен пропускной способностью памяти, поэтому увеличение m улучшает производительность.
GEMM
Ядро GEMM соответствует Linear Projections в модели, таких как Q/K/V/O Projection. Для умножения матриц [m, k] x [k, n] -> [m, n] количество FLOP составляет 2 * m * k * n, а байты ввода-вывода памяти — m * k + n * k + m * n. Мы также можем протестировать задержку для размеров пакетов 1-128.
Рисунок выше показывает модель Roofline для GEMM при различных конфигурациях EP. Мы видим, что производительность GEMM ограничена пропускной способностью памяти. По мере увеличения размера пакета арифметическая интенсивность также увеличивается, тем самым улучшая производительность.
Microbatch
При использовании микропакетирования мы делим пакет поровну на две части. Из двух рисунков выше видно, что когда m становится m/2, эффективность умножения матриц снижается. Следовательно, выполнение двух умножений матриц размера m/2 занимает больше времени, чем выполнение одного умножения матриц размера m.
Multi-Token Prediction
На протяжении всей статьи мы предполагали использование Multi-Token Prediction (MTP) для спекулятивного декодирования. MTP изменяет длину запроса на запрос с 1 до 2. Для умножения матриц это эквивалентно изменению m на m * 2, тем самым увеличивая эффективность умножения матриц. С другой стороны, если мы построим модель Roofline для MLA, мы обнаружим, что увеличение длины запроса значительно повышает эффективность ядра MLA.
Поэтому использование MTP играет важную роль в эффективности модели.
Реализация и оптимизация
В этом разделе мы представим некоторые подробности реализации и оптимизации для нашей модели DeepSeek-V3/R1.
Квантование
DeepSeek-V3/R1 была изначально обучена на FP8 с использованием схемы блочного квантования, где веса квантуются статически, а активации — «на лету». Вместо статического вычисления коэффициента масштабирования по каналам или по матрицам, коэффициенты масштабирования вычисляются по векторам из 128 элементов для активаций и по блокам 128x128 элементов для матриц, что ограничивает снижение точности из-за квантования.
В Perplexity мы полагаемся на смесь ядер CUDA и Triton для поддержки вывода, причем CUDA используется для наиболее чувствительных к производительности и редко изменяемых ядер (таких как внимание и GEMM), а Triton реализует широкий спектр ядер активации, нормализации и служебных ядер. Triton позволил нам быстро адаптировать ядра к схеме блочного квантования.
Для слоев linear и MoE мы смешиваем ядра Deep GEMM с нашими собственными ядрами Triton GEMM, так как заметили, что для определенных размерностей матриц и малых размеров пакетов Split-K обеспечивает меньшую задержку. Если неквантованный слой выполняет умножение (M, K) x (K, N), ему требуется коэффициент масштабирования (M x ceil_div(K, 128)) x (ceil_div(K, 128), ceil_div(N, 128)) для блочного квантования. Для блочного квантования коэффициенты масштабирования для активаций вычисляются «на лету», а не предварительно калибруются. Поскольку коэффициенты масштабирования активации агрегируются только вдоль измерения K, а не вдоль измерения M, ядра требуют лишь незначительных изменений для поддержки этой схемы.
Функция активации SiLU, используемая DeepSeek-V3/R1, потребовала существенных изменений для поддержки графов CUDA, блочного квантования и динамически маршрутизируемых количеств токенов. Блочное квантование может быть проблематичным, так как оно вводит горизонтальные редукции, однако ядро уже разбивало активации вдоль их скрытого измерения на блоки по 1024 элемента. Внутри одного блока тензор, подлежащий квантованию, дополнительно разбивался на блоки по 128 для вычисления наибольшего абсолютного значения, при этом Triton генерировал эффективные кросс-варп макс-редукции, добавляя минимальные накладные расходы.
Для поддержки маршрутизации MoE в графах CUDA ядра должны знать информацию о маршрутизации, указывающую количество токенов на эксперта, вместо планирования работы на основе размера буферов, выделенных для хранения верхней границы количеств токенов. Мы не можем разделить проблему на основе размерностей входного тензора, поэтому мы запускаем фиксированное количество постоянных ядер, которые считывают информацию о маршрутизации, чтобы определить, сколько токенов заполнено, и динамически распределяют между ними работу по обработке активаций.
Мы уже отправили некоторые из наших ядер в проект FlashInfer, и в будущем мы будем открывать больше нашего кода.
Слой MLA
Мы используем FlashInfer для вычислений MLA. FlashInfer поддерживает гибкие настройки таблицы страниц и чрезвычайно высокую производительность.
Мы объединили q_a_proj и kv_a_proj в одну qkv_a_proj. Задержка снизилась с 15,4 мкс + 14,8 мкс = 30,2 мкс до 16,7 мкс.
Мы разложили kv_b_proj на две матрицы, k_b_proj и v_b_proj. Мы написали ядро FP8 Block Quantized BMM для вычислений, связанных с этими двумя матрицами.
Граф Cuda
Граф Cuda может значительно сократить накладные расходы на запуск ядра, что критически важно для производительности. Мы создаем граф Cuda для каждого размера пакета.
До разработки нашего ядра AllToAll мы использовали torch.all_to_all_single() для взаимодействия AllToAll. Эта операция требует, чтобы все GPU использовали одинаковый размер пакета. Однако разные группы DP могут запускать разные размеры пакетов.
Чтобы гарантировать совместимость all_to_all_single() с разными группами DP, использующими разные размеры пакетов, мы сначала использовали операцию allreduce() перед каждым запуском модели, чтобы получить максимальный размер пакета среди всех групп DP. Затем мы заставили все группы DP использовать этот размер пакета для запуска.
Хотя этот подход гарантирует, что мы можем использовать граф Cuda, он имеет три недостатка. Во-первых, он требует дополнительной операции allreduce(). Во-вторых, группы DP с меньшими размерами пакетов вынуждены использовать заполнение. В-третьих, это усложняет код нашей реализации.
После реализации нашего собственного ядра AllToAll нам больше не требуется, чтобы все GPU использовали одинаковый размер пакета. Следовательно, нам больше не нужно выполнять дополнительные операции allreduce() или заполнять размеры пакетов.
Маршрутизатор MoE
Маршрутизатор MoE реализован в Triton и опирается на модифицированную сортировку, производную от стандартной библиотеки, которая также отслеживает индексы отсортированных элементов. Реализация является общей для всех моделей MoE, так как маршрутизация Mixtral является частным случаем маршрутов DeepSeek, где группа Top-K совпадает с группой всех экспертов. Разреженные ядра потребляют индексы и оценки Top-K напрямую, тогда как плотные схемы диспетчеризации/комбинирования, полагающиеся на all-to-all, требуют, чтобы информация о маршрутизации агрегировалась по экспертам, а не по токенам.
Будущая работа
В будущей работе мы планируем дальнейшую оптимизацию производительности модели DeepSeek.
Самая важная следующая оптимизация — дезагрегация Prefill. Фазы Prefill и Decode модели DeepSeek-V3/R1 имеют очень разные вычислительные характеристики. Обе могут использовать различные стратегии оптимизации и схемы развертывания.
Для слоя MLA на этапе Decode мы используем матричное поглощение для уменьшения количества FLOP вычислений MLA. На этапе Prefill сначала проецирование латентного вектора в пространство K/V, а затем вычисление в форме Multi-Head Attention (MHA) показало бы лучшие результаты.
Если Prefill и Decode работают на одном GPU, чтобы уменьшить влияние Prefill на скорость вывода Decode, мы обычно используем chunked prefill для разделения запроса на несколько частей для Prefill. Поскольку KV-кэш хранит латентный вектор, становится трудно преобразовать MLA в форму MHA.
Для слоя MoE на этапе Decode мы используем как можно большие EP и DP, чтобы увеличить количество входных токенов на эксперта, тем самым улучшая производительность GroupGEMM. На этапе Prefill, поскольку количество токенов уже достаточно велико, GroupGEMM уже ограничено вычислениями. Поэтому для Prefill мы можем использовать меньшие EP и DP.
Если Prefill и Decode работают на одном GPU, пока любая группа DP выполняет Prefill, задержка слоев MoE на всех GPU будет увеличиваться, что значительно влияет на скорость вывода Decode.
Помимо дезагрегации Prefill, мы также планируем оптимизировать следующие аспекты:
Производительность AllToAll: наше ядро AllToAll в настоящее время может достичь только 1/3 пропускной способности Infiniband. Мы продолжим оптимизировать это ядро.
Спекулятивное декодирование в стиле EAGLE: в приведенных выше данных мы предположили использование спекулятивного декодирования для предсказания 1 токена. EAGLE может использовать древовидную структуру для предсказания нескольких токенов, улучшая длину принятия, что может значительно увеличить скорость вывода.
Ядро GEMM: в модели Roofline, показанной ранее, мы можем обнаружить, что эффективность ядра GEMM все еще далека от теоретического предела. Мы продолжим оптимизировать это ядро.
GB200 NVL72: в новейшем решении NVIDIA GB200 NVL72 72 GPU Blackwell соединены друг с другом через высокоскоростной NVLink. Для моделей с архитектурой MoE это очень большая возможность и вызов.
Заключение
Многоузловое развертывание моделей DeepSeek MoE достигает того, что обычно невозможно для плотных LLM: одновременное улучшение пропускной способности и задержки. Распределяя экспертов по большему количеству GPU, мы снижаем нагрузку на пропускную способность памяти на устройство, обеспечивая более быструю обработку и более высокую пропускную способность системы. Наши эксперименты показывают, что конфигурации EP128 достигают до 5 раз более высокой пропускной способности при эквивалентных скоростях вывода по сравнению с одноузловыми развертываниями.
Методы перекрытия вычислений и взаимодействия, такие как микропакетирование, значительно снижают накладные расходы на многоузловое взаимодействие, причем наша реализация показывает ускорение до 40%. Наши пользовательские ядра взаимодействия AllToAll и оптимизированные реализации ядер позволили эффективно развернуть модель с 671 млрд параметров.
Поскольку архитектуры MoE приобретают популярность благодаря своим возможностям, эти стратегии развертывания предоставляют ценную информацию для эффективного масштабирования таких моделей.
Ссылки
Обзор системы вывода DeepSeek-V3/R1
Megatron-LM: Обучение многомиллиардных языковых моделей с использованием параллелизма моделей
EAGLE: Спекулятивная выборка требует переосмысления неопределенности признаков
Цитирование
@online{perplexity2025LowerLatencyAndHigherThroughputWithMultiNodeDeepseekDeployment,
author = {{Perplexity} and Lequn Chen and Nandor Licker and Erin McKnight},
title = {{Lower latency and higher throughput with multi-node DeepSeek deployment}},
date = {2025-04-18},
url = {https://perplexity.coolkeypoint.com/hub/blog/lower-latency-and-higher-throughput-with-multi-node-deepseek-deployment}
}