Статья
Низкая задержка и высокая пропускная способность при развертывании Multi-Node DeepSeek

В большинстве систем задержка и пропускная способность часто являются конфликтующими целями, требующими компромиссов при проектировании и развертывании. Например, в плотных моделях с масштабными языковыми моделями увеличение размера пакета может улучшить пропускную способность, но также увеличивает задержку; увеличение параллелизма тензоров в пределах одной машины может уменьшить задержку, но снижает количество реплик, что ведет к уменьшению пропускной способности.
Модели смеси экспертов (MoE), такие как DeepSeek-V3/R1, недавно продемонстрировали отличные возможности моделей и оперативную эффективность. Например, модель DeepSeek-V3/R1 имеет общую число параметров 671 миллиардов, но каждый токен использует только 37 миллиардов параметров в процессе инференса. Эта архитектура модели представляет собой как вызовы, так и возможности для систем инференса.
Эта статья демонстрирует, что, вопреки традиционным системам, модели MoE, такие как DeepSeek-V3/R1, могут одновременно достигать более высокой пропускной способности и меньшей задержки, используя больше GPU в многозадачевых развертываниях в большинстве сценариев.
Архитектуры развертывания


Из-за большого количества небольших экспертов в модели, развертывания должны быть распределены по множеству устройств. Мы рассматривали как развертывания на одном узле с 8xH200 GPU, так и многозадачные развертывания на 8xH100 GPU.
Обе архитектуры развертывания используют параллелизм данных, организованный нашим внутренним диспетчером запросов. Реализация параллелизма данных включает запуск нескольких экземпляров движка инференса, каждый из которых работает независимо для обработки и поддержки запросов. Диспетчер запросов взаимодействует с движком через GRPC, отвечая за максимально равномерное распределение запросов и содействие повторному использованию KV, отправляя запросы с частично совпадающим префиксом на серверы с кэшем. Экземпляры движка не охватывают множество узлов. Они могут использовать параллелизм тензоров для разбиения внимания между несколькими устройствами. Экземпляры связаны через NVLink в случае одного узла или через InfiniBand для многозадачного варианта, распределяя и собирая экспертов.
Конфигурация развертывания на одном узле обеспечивает превосходную задержку при небольших размерах пакета; однако производительность быстро ухудшается при увеличении нагрузки.
Чтобы развернуть движок обслуживания, мы запускаем один под на узел, который размещает несколько экземпляров движка. PyTorch отвечает за настройку распределенной коммуникации и согласование инициализации NVSHMEM. Для коммуникации мы полагаемся на пользовательские CUDA-ядра, описанные в предыдущем блоге. Реализация двух развертываний практически идентична, модель выбирает правильные ядра для использования в зависимости от структуры, реализующей параллелизм экспертов.
Методы параллелизации
Перед тем как приступить к сравнению производительности, важно понять ключевые стратегии параллелизации, которые делают возможным развертывание массивных моделей MoE, таких как DeepSeek-V3/R1.
Параллелизм тензоров
В инференсе LLM параллелизм тензоров (TP) обычно используется для сокращения использования памяти и вычислений на GPU, тем самым уменьшая задержку. Обычно мы можем разделить линейные проекции в слоях внимания и MLP по строкам или столбцам, а операции внимания по размерности головки внимания.
С TP архитектура Llama-3 не дублирует вычисления для линейных проекций и операций внимания по GPU, что является идеальным методом разбиения. Однако, в моделях DeepSeek-V3/R1 TP этого добиться не удается.
Модели DeepSeek-V3/R1 используют многолатентное внимание (MLA). Слой MLA сначала использует линейную проекцию kv_a_proj для вычисления латентного вектора, затем использует другую линейную проекцию kv_b_proj для преобразования его в пространство каждой головки внимания. Поскольку все головки внимания делятся одним латентным вектором, TP не может разделить латентный вектор, поэтому все TP ранги должны дублировать параметры и вычисления kv_a_proj и kv_b_proj. Также, поскольку MLA хранит латентный вектор в KV Cache, каждый TP ранг хранит идентичную копию KV Cache.
Несмотря на некоторое дублирование в 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 слоя MLA и TP можно комбинировать, когда одна группа DP разделена на несколько рангов TP. Слой MoE EP можно комбинировать с DP/TP слоя MLA. EP = DP * TP. Например, на 16 машинах конфигурация EP128 DP32 TP4 означает распределение маршрутизируемых экспертов по 128 GPU, каждые 4 GPU формируют группу DP, в сумме образуется 32 независимые группы DP.
Развертывание на одном узле против многозадачного
671B параметров DeepSeek превышают объем памяти одной 8-GPU машины H100 (80 ГБ * 8), но одна 8-GPU машина H200 может полностью вместить всю модель (141 ГБ * 8). Используя конфигурацию EP8 DP8 TP1, модель использует около 100 ГБ памяти на GPU, оставляя примерно 40 ГБ для KV Cache и других промежуточных результатов. Один токен занимает 70,272 байта KV Cache. Предполагая, что каждый запрос имеет 5,000 токенов, каждый GPU может обработать около 100 запросов.
Мы хотели понять различия в производительности между развертываниями на аналогичных конфигурациях на одном узле и многозадачных. Мы использовали одну H200 машину для развертывания на одном узле и до 16 H100 машин для многозадачных развертываний. Для каждой среды развертывания мы использовали комбинации TP 1, 2, 4, 8 и размеров пакета на GPU 1, 2, 4, 8, 16, 32, 64, 128. Мы предполагали, что каждый запрос имеет длину KV Cache 5000 токенов. Мы также предполагали, что Multi-Token Prediction (MTP) предсказывает 1 дополнительный токен (т.е., длина запроса каждого запроса 2), и консервативно предполагали коэффициент принятия 60%. На рисунке ниже показаны пропускная способность и скорость вывода для различных конфигураций.

Ось абсцисс представляет скорость вывода на запрос в токенах/с. Ось ординат использует логарифмическую шкалу для отображения пропускной способности на машину в токенах/с. Мы отметили Pareto Frontier для каждой конфигурации 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 смещают Pareto Frontier к одновременным улучшениям как пропускной способности, так и скорости вывода.
Использование более высокого числа 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, а затем ожидать завершения получения Dispatch. Мы называем эту схему перекрытия "Dispatch Overlap".
Dispatch Overlap предлагает простое внедрение и широкую применимость. Эта техника скрывает время вычислений общего эксперта во всех размерах EP и размерах пакета.
Чтобы еще больше увеличить перекрытие вычислений и коммуникации, мы использовали микроразбивку, упомянутую в техническом отчете DeepSeek, для устранения зависимости данных. Как показано в нижней части рисунка, мы разделили вычисления одного слоя Transformer на 5 этапов:
Этап 1: InputNorm, QKVProj, AppendixKV, BMM
Этап 2: BMM, Attn, OProj, PostNorm, Gate
Этап 3: Отправка Dispatch, Общий эксперт
Этап 4: Получение Dispatch, MoE, Отправка Combine
Этап 5: Получение Combine
В первых 3 плотных слоях Transformer мы используем весь пакет. В следующих 58 слоях MoE Transformer мы равномерно делим пакет на два микропакета. Два микропакета исполняются поочередно, с разницей в 3 этапа. Так как отсутствует зависимость данных между этими двумя микропакетами, мы можем переключиться на выполнение вычислений другого микропакета после отправки Dispatch и после отправки Combine.
Разбиение задержки
Далее мы сравниваем эффекты перекрытия с помощью эксперимента, а также сравниваем различия в производительности между развертыванием на одном узле EP8 и многозадачным развертыванием EP128. Для удобства сравнения мы использовали GPU H100 для следующего эксперимента. Мы использовали TP1, размер пакета 128 на GPU, длину запроса 2 на запрос и длину KV Cache 5000.

На рисунке выше показано общее время, проведенное на одном слое MoE Transformer и процент задержки разных типов ядер. За исключением Dispatch, Combine и GroupGEMM, время выполнения остальных ядер должно быть одинаковым в сериях EP8, EP128 NoOverlap и EP128 DispatchOverlap, поскольку размер пакета одинаков.
Перекрытие
Сначала сравним эффекты трех методов перекрытия. NoOverlap заняло в общей сложности 2667 мкс, DispatchOverlap заняло 2651 мкс, сэкономив 16 мкс или всего 0,6%. Микроразбиение показало значительное улучшение, заняв 1896 мкс, 29% ускорение. Как Dispatch, так и Combine время значительно сократилось. Dispatch уменьшился с 593 мкс до 367 мкс, а Combine с 1012 мкс до 237 мкс.
Обратите внимание, что для вычислительных ядер, разделение пакета размером 128 на два пакета по 64 увеличивает общее время выполнения. Поэтому, хотя время, затрачиваемое на коммуникацию сократилось на 1001 мкс, общее время только сократилось на 771 мкс. Мы объясним причину, используя Roofline модель в следующем разделе.
По этой причине микроразбиение не всегда улучшает производительность.

На рисунке выше показано улучшение производительности микроразбиения по сравнению с DispatchOverlap для размеров пакета 4-128. Когда размер пакета меньше 32, микроразбиение снижает производительность на 5%-40%. Когда размер пакета больше или равен 32, микроразбиение может улучшить производительность на 10%-35%.
EP8 против EP128
Вернемся к предыдущему рисунку и сравним EP8 и EP128 Microbatch. EP8 занял в общей сложности 1802 мкс, немного меньше, чем EP128 с 1896 мкс. Помимо увеличенного времени выполнения ядер, вызванного микроразбиением, основные различия заключаются в использовании GroupGEMM для вычислений MoE и двух ядер коммуникации, Dispatch и Combine.
Время выполнения GroupGEMM на EP8 заняло 555 мкс, в то время как GroupGEMM на EP128 заняло 270 мкс, уменьшившись наполовину. Это основное преимущество многозадачного развертывания.
К сожалению, время, затраченное на коммуникацию, увеличилось на 213 мкс, что сильно нивелировало преимущество GroupGEMM. В отдельных тестах производительности наших ядер коммуникации, мы выяснили, что они могут достигать только половины максимальной пропускной способности InfiniBand. Мы продолжим оптимизировать наши ядра коммуникации.
Другое ядро, которое значительно отстает, это GEMM. Микроразбиение увеличило GEMM на 95 мкс. Мы углубленно проанализируем GEMM в разделе Roofline ниже. Мы считаем, что нынешняя реализация GEMM еще не достигла оптимальной производительности.
Roofline
Модель Roofline — это хороший инструмент для анализа производительности ядер. Ее горизонтальная ось представляет арифметическую интенсивность, соотношение FLOP к байтам I/O памяти. Значение горизонтальной оси можно рассчитать напрямую из семантики ядра. Вертикальная ось представляет достигнутую производительность, рассчитываемую делением FLOP на длительность работы.
Теоретическая верхняя граница производительности ядра напрямую определяется характеристиками GPU. Пиковая производительность FP8 H100 составляет 1979 TFLOP/с, представленная горизонтальной линией в модели 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, а байты I/O памяти составляют 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 соответствует линейным проекциям в модели, таким как Q/K/V/O Projection. Для умножения матриц [m, k] x [k, n] -> [m, n] количество FLOP составляет 2 * m * k * n, а байты I/O памяти составляют m * k + n * k + m * n. Мы также можем протестировать задержку для размеров пакета от 1 до 128.

На рисунке выше показана модель Roofline для GEMM под различными конфигурациями EP. Мы видим, что производительность GEMM ограничена пропускной способностью памяти. По мере увеличения размера пакета арифметическая интенсивность также увеличивается, улучшая производительность.
Микроразбиение
При использовании микроразбиения мы делим пакет ровно на две части. Из двух рисунков выше видно, что когда m становится m/2, эффективность умножения матриц уменьшается. Поэтому выполнение двух умножений матриц размера m/2 занимает больше времени, чем выполнение одного умножения матриц размера m.
Многотокеновое предсказание
На протяжении этой статьи мы предполагали использование многотокенового предсказания (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 позволил нам быстро адаптировать ядра к схеме квантования по блоку.
Для линейных и 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 и Decode модели DeepSeek-V3/R1 имеют очень разные вычислительные характеристики. Обе могут использовать разные стратегии оптимизации и схемы развертывания.
Для слоя MLA в фазе Decode мы используем поглощение матрицы для уменьшения количества FLOP в вычислениях MLA. В фазе Prefill сначала проекция латентного вектора в пространство K/V, а затем вычисление в форме многоголовного внимания (MHA) работает лучше.
Если Prefill и Decode выполняются на одном GPU, чтобы снизить влияние Prefill на скорость вывода Decode, мы обычно используем разделенное заполнение, чтобы разделить запрос на несколько частей для Prefill. Поскольку KV Cache хранит латентный вектор, становится сложно преобразовать MLA в форму MHA.
Для слоя MoE в фазе Decode мы используем максимальные EP и DP, чтобы увеличить количество входных токенов на эксперта, тем самым улучшая производительность GroupGEMM. В фазе Prefill, потому что количество токенов уже велико, GroupGEMM уже вычислительно ограничен. Поэтому для Prefill мы можем использовать меньшие EP и DP.
Если Prefill и Decode выполняются на одном GPU, пока любая группа DP выполняет Prefill, задержка слоев MoE на всех GPU будет увеличиваться, сильно влияя на скорость вывода Decode.
Кроме дизагрегации заполнения, мы также планируем оптимизировать следующие аспекты:
Производительность All-To-All: Наше ядро All-To-All в настоящее время может достигать только 1/3 пропускной способности InfiniBand. Мы продолжим оптимизировать это ядро.
EAGLE-style спекулятивное декодирование: В приведенных выше данных мы предполагали использование спекулятивного декодирования для предсказания одного токена. EAGLE может использовать древесную структуру для предсказания нескольких токенов, увеличивая длину принятия, что может значительно увеличить скорость вывода.
Ядро GEMM: В показанной ранее модели Roofline мы можем видеть, что эффективность ядра GEMM все еще далека от теоретического предела. Мы продолжим оптимизировать это ядро.
GB200 NVL72: В новейшем решении NVIDIA GB200 NVL72 72 Blackwell GPU связаны высокоскоростным NVLink. Для моделей с архитектурой MoE это большая возможность и вызов.
Заключение
Многозадачное развертывание моделей DeepSeek MoE достигает того, что обычно невозможно с плотными LLM: одновременное улучшение как пропускной способности, так и задержки. Распределяя экспертов между более чем GPU, мы снижаем давление на пропускную способность памяти на устройство, позволяя более быструю обработку и более высокую систему пропускной способности. Наши эксперименты показывают, что конфигурации EP128 достигают до 5-кратного увеличения пропускной способности при эквивалентной скорости вывода по сравнению с развертыванием на одном узле.
Техники перекрытия вычислений и коммуникации, такие как микроразбиение, значительно сокращают накладные расходы на многозадачную коммуникацию, при этом наша реализация показывает до 40-процентное ускорение. Наши собственные ядра коммуникации All-To-All и оптимизированные реализации ядер позволяют эффективно развернуть модель с 671 миллиардами параметров.
Поскольку архитектура MoE набирает популярность благодаря своим возможностям, эти стратегии развертывания предоставляют ценные идеи для масштабирования таких моделей эффективно.