다중 노드 DeepSeek 배포를 통한 지연 시간 단축 및 처리량 향상

다중 GPU 배포는 MoE 모델 성능을 속도와 규모 면에서 동시에 향상시킵니다.

작성자Perplexity Research

대부분의 시스템에서 지연 시간과 처리량은 종종 상충하는 목표이며, 설계 및 배포 과정에서 상호 절충이 필요합니다. 예를 들어, 대규모 언어 모델의 경우 배치 크기를 늘리면 처리량은 향상될 수 있지만 지연 시간 또한 증가합니다. 반면 단일 머신 내에서 텐서 병렬성을 높이면 지연 시간은 줄일 수 있으나 복제본 수가 감소하여 결과적으로 처리량이 낮아집니다.

DeepSeek-V3/R1과 같은 전문가 혼합(MoE) 모델은 최근 뛰어난 모델 성능과 운영 효율성을 입증했습니다. 예를 들어 DeepSeek-V3/R1 모델은 총 6,710억 개의 매개변수를 보유하고 있으나, 추론 시 각 토큰은 370억 개의 매개변수만을 사용합니다. 이러한 모델 아키텍처는 추론 시스템에 도전 과제와 기회를 동시에 제시합니다.

본 게시글은 기존 시스템과 달리 DeepSeek-V3/R1과 같은 MoE 모델이 대부분의 시나리오에서 다중 노드 배포 시 더 많은 GPU를 활용하여 더 높은 처리량과 더 낮은 지연 시간을 동시에 달성할 수 있음을 입증합니다.

배포 아키텍처

NVLink를 통한 단일 노드 배포로, 어텐션과 전문가 계산이 GPU 간에 분산됩니다.
InfiniBand를 통한 멀티노드 배포로, GPU 그룹이 노드 내부와 노드 간에 연결됩니다.

모델이 보유한 다수의 소형 전문가로 인해 배포는 여러 장치에 분산되어야 합니다. 당사는 8xH200 GPU를 탑재한 단일 노드에서의 배포와 8xH100 GPU를 탑재한 다중 노드 배포 방식을 모두 고려했습니다.

두 배포 아키텍처 모두 사내 요청 스케줄러를 통해 조정되는 데이터 병렬성을 활용합니다. 데이터 병렬성 구현에는 요청을 처리하고 유지하기 위해 독립적으로 작동하는 여러 추론 엔진 인스턴스를 실행하는 것이 포함됩니다. GRPC를 통해 엔진과 상호 작용하는 요청 스케줄러는 캐시를 포함하는 서버로 부분적으로 일치하는 접두사가 있는 요청을 전송하여 KV 재사용을 촉진하는 동시에, 요청을 최대한 균등하게 분산할 책임이 있습니다. 엔진 인스턴스는 여러 노드에 걸쳐 확장되지 않습니다. 필요에 따라 텐서 병렬성을 사용하여 여러 장치에 걸쳐 어텐션을 샤딩할 수 있습니다. 각 인스턴스는 단일 노드 사례의 경우 NVLink로, 다중 노드 사례의 경우 InfiniBand로 상호 연결되어 전문가를 디스패치 및 수집합니다.

단일 노드 배포 구성은 작은 배치 크기에서 우수한 지연 시간을 제공하지만, 부하가 증가하면 성능이 급격히 저하됩니다.

서빙 엔진을 배포하기 위해 노드당 하나의 포드를 실행하고 여러 엔진 인스턴스를 호스팅합니다. PyTorch는 분산 통신을 설정하고 NVSHMEM 초기화를 협상하는 역할을 합니다. 통신을 위해 당사는 이전 블로그 게시물에서 설명한 사용자 지정 CUDA 커널을 사용합니다. 두 배포 방식의 구현은 사실상 동일하며, 모델은 전문가 병렬성을 구현하는 패브릭을 기반으로 사용할 올바른 커널을 선택합니다.

병렬화 기법

성능 비교를 시작하기 전에 DeepSeek-V3/R1과 같은 거대한 MoE 모델 배포를 가능하게 하는 핵심 병렬화 전략을 이해하는 것이 필수적입니다.

텐서 병렬성

LLM 추론에서 텐서 병렬성(TP)은 일반적으로 GPU당 메모리 사용량과 연산량을 줄여 지연 시간을 낮추는 데 사용됩니다. 보통 어텐션 및 MLP 레이어의 Linear 투영을 행 또는 열 차원을 따라 샤딩하고, 어텐션 헤드 차원을 따라 어텐션 연산을 샤딩할 수 있습니다.

TP를 사용하면 Llama-3 아키텍처는 GPU 간의 Linear 투영 및 어텐션 연산에 중복 연산이 없어 이상적인 샤딩 방식이 됩니다. 그러나 DeepSeek-V3/R1 모델에서는 TP로 이를 달성할 수 없습니다.

DeepSeek-V3/R1 모델은 MLA(Multi-Latent Attention)를 사용합니다. MLA 레이어는 먼저 Linear 투영 kv_a_proj을 사용하여 잠재 벡터를 계산한 다음, 다른 Linear 투영 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에서 계산 결과를 수집하고 가중 합산을 수행합니다. 당사는 NVSHMEM을 사용하여 이러한 두 가지 AllToAll 통신 커널인 Dispatch와 Combine의 최적화된 버전을 구현했습니다. 이전 블로그 게시물에서 구현에 대해 자세히 설명했으며, 당사의 커널은 GitHub에 오픈 소스로 공개되었습니다.

데이터 병렬성

EP를 사용하면 128개 이상의 GPU에 MoE 연산을 분산할 수 있습니다. 그러나 MLA 연산은 EP로 파티셔닝할 수 없습니다. 이 시점에서 데이터 병렬성(DP)을 도입할 수 있습니다. 각 DP 그룹은 MLA 레이어의 전체 복사본을 가집니다. 각 DP 그룹은 서로 다른 입력을 수용하고 MLA 레이어 연산을 독립적으로 수행합니다.

MLA 레이어의 DP와 TP는 결합될 수 있으며, 하나의 DP 그룹이 여러 TP 랭크로 나뉩니다. MoE 레이어의 EP는 MLA 레이어의 DP/TP와 결합할 수 있습니다. EP = DP * TP입니다. 예를 들어 16대의 머신에서 EP128 DP32 TP4는 라우팅된 전문가를 128개의 GPU에 분산하고, 4개의 GPU마다 하나의 DP 그룹을 형성하여 총 32개의 독립적인 DP 그룹을 구성하는 것을 의미합니다.

단일 노드 vs 다중 노드

DeepSeek의 6,710억 개 매개변수는 단일 8-GPU H100 머신(80GB * 8)의 메모리 용량을 초과하지만, 단일 8-GPU H200 머신은 전체 모델(141GB * 8)을 완전히 수용할 수 있습니다. EP8 DP8 TP1 구성을 사용하면 모델은 GPU당 약 100GB의 메모리를 사용하며, KV 캐시 및 기타 중간 결과를 위해 약 40GB가 남습니다. 토큰 하나는 70,272바이트의 KV 캐시를 차지합니다. 각 요청이 5,000개의 토큰을 가진다고 가정할 때 각 GPU는 약 100개의 요청을 수용할 수 있습니다.

당사는 다양한 구성에서 단일 노드 배포와 다중 노드 배포 간의 성능 차이를 이해하고자 했습니다. 단일 노드 배포에는 H200 머신 1대를, 다중 노드 배포에는 최대 16대의 H100 머신을 사용했습니다. 각 배포 환경에 대해 TP 1, 2, 4, 8 조합과 GPU당 배치 크기 1, 2, 4, 8, 16, 32, 64, 128을 사용했습니다. 각 요청의 KV 캐시 길이는 5,000토큰으로 가정했습니다. 또한 MTP(Multi-Token Prediction)가 1개의 추가 토큰을 예측한다고(즉, 각 요청의 쿼리 길이는 2) 가정하고, 60%의 수락률을 보수적으로 가정했습니다. 아래 그림은 다양한 구성에 대한 처리량과 출력 속도를 보여줍니다.

서로 다른 전문가 병렬 구성에 대한 지연 시간–처리량 파레토 최전선.

가로축은 요청당 출력 속도(토큰/초)를 나타냅니다. 세로축은 머신당 처리량(토큰/초)을 로그 스케일로 표시합니다. 각 EP 구성에 대한 파레토 최적점을 서로 다른 색상의 선으로 표시했습니다.

매우 높은 출력 속도 요구 사항이 있는 시나리오에서 배치 크기가 1인 단일 노드 EP8 DP1 TP8을 사용하면 100토큰/초를 초과하는 출력 속도를 달성할 수 있지만, 처리량은 출력 속도와 동일한 수준으로 매우 낮습니다. 이 시나리오에서 전체 배치는 토큰이 2개뿐이며, 이는 최대 2*8=16개의 전문가에게 디스패치되어 최대 570억 개의 매개변수를 활성화합니다.

80-40토큰/초의 출력 속도 범위에서는 처리량이 증가함에 따라 출력 속도가 현저히 감소합니다. 반면 EP128은 동일한 출력 속도에서 단일 노드 배포보다 약 5배 더 높은 처리량을 보입니다.

이 현상은 단일 노드 배포의 동작을 살펴보면 설명할 수 있습니다. 배치 크기를 늘리면 활성화되는 전문가 수와 직접적으로 상관관계가 있습니다. 배치 크기가 1일 때 GPU당 활성화된 평균 전문가 수는 2 * 8 / 8 = 2입니다. 배치가 충분히 크면 모든 전문가가 활성화되므로 각 GPU는 256 / 8 = 32개의 전문가를 활성화합니다. 더 많은 전문가를 활성화한다는 것은 GPU가 메모리에서 더 많은 매개변수를 읽어야 함을 의미하며, 이는 메모리 대역폭 압력을 크게 증가시킵니다. 대규모 언어 모델의 디코드 단계는 이미 연산 성능이 아닌 메모리 대역폭에 의해 병목 현상이 발생하므로, 단일 노드 배포에서 배치 크기를 늘리면 출력 속도가 크게 줄어듭니다.

4가지 다중 노드 배포 구성(EP16, EP32, EP64, EP128)을 비교하면 EP 값이 높을수록 파레토 최적점이 처리량과 출력 속도를 동시에 개선하는 방향으로 이동함을 알 수 있습니다.

더 높은 EP 번호를 사용하면 각 GPU에 할당되는 전문가 수가 줄어듭니다. 예를 들어 EP128은 각 GPU가 256 / 128 = 2개의 전문가를 담당함을 의미하므로 메모리 대역폭 압력이 크게 감소합니다. 즉, 더 큰 EP 번호를 사용하면 사실상 더 많은 메모리 대역폭을 얻게 됩니다. GPU당 배치 크기가 64 미만일 때는 배치 크기를 늘려도 입력 수가 늘어남에 따라 메모리 대역폭 압력이 크게 증가하지 않으므로 전문가 연산 속도에 큰 영향을 미치지 않습니다. 따라서 EP128을 사용할 때 배치 크기를 늘려도 출력 속도가 크게 영향을 받지 않는 것을 볼 수 있습니다.

흥미롭게도 더 큰 배치 크기(GPU당 64개 요청)에서 새로운 현상이 관찰되었습니다. 단일 노드 배포의 처리량이 다중 노드 배포보다 약간 높게 나타난 것입니다. 그 이유 중 하나는 노드 내 NVLink가 노드 간 InfiniBand보다 대역폭이 높기 때문입니다. 다른 이유는 당사 구현의 한계 때문입니다. 이 현상은 나중에 더 자세히 분석할 예정입니다.

메모리 용량 제한으로 인해 EP8 DP8 TP1 구성은 GPU당 128개의 배치 크기에 도달할 수 없으므로, 더 높은 처리량을 추구하는 시나리오에서는 여전히 다중 노드 배포가 더 나은 선택입니다.

연산 및 통신 중첩

위에서 전문가 병렬성에 대해 간략히 소개한 바와 같이, MoE 레이어 통신 중에 GPU는 유휴 상태가 됩니다. 이러한 낭비를 줄이고 지연 시간을 낮추기 위해 유휴 시간을 채울 수 있는 데이터 독립적인 연산 작업을 찾아야 합니다.

중첩이 없는 계산 및 통신 스케줄, 디스패치 중첩, 그리고 5단계 파이프라인.

위 그림의 상단 부분은 한 레이어의 연산 흐름을 보여줍니다. MoE 연산은 Dispatch에 의존하며, 다음 레이어의 연산은 Combine의 결과에 의존합니다.

당사는 각 GPU에 공유 전문가를 배치합니다. 이렇게 하면 공유 전문가 연산에 AllToAll 통신이 필요하지 않습니다. 따라서 Dispatch Send 직후에 공유 전문가 연산을 수행한 다음 Dispatch Recv가 완료되기를 기다릴 수 있습니다. 이를 "Dispatch 중첩"이라고 합니다.

Dispatch 중첩은 구현이 간단하고 적용 범위가 넓습니다. 이 기술은 모든 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 간의 성능 차이를 비교합니다. 비교의 편의를 위해 다음 실험에는 H100 GPU를 사용했습니다. TP1, GPU당 배치 크기 128, 요청당 쿼리 길이 2, KV 캐시 길이 5000을 사용했습니다.

비교한 전문가 병렬 및 중첩 구성의 커널별 레이어 지연 시간.

위 그림은 한 개의 MoE Transformer 레이어에 소요된 총 시간과 커널 유형별 지연 시간 비중을 보여줍니다. Dispatch, Combine, GroupGEMM을 제외하고는 배치 크기가 동일하기 때문에 EP8, EP128 NoOverlap 및 EP128 DispatchOverlap 시리즈에서 다른 커널의 실행 시간은 같아야 합니다.

중첩

먼저 세 가지 중첩 방법의 효과를 비교해 보겠습니다. NoOverlap은 총 2667µs가 소요되었고, DispatchOverlap은 2651µs가 소요되어 16µs(0.6%)의 시간만 절약되었습니다. MicroBatch는 매우 상당한 개선을 보여 1896µs로 29%의 속도 향상을 보였습니다. Dispatch 및 Combine 시간이 크게 줄었습니다. Dispatch는 593µs에서 367µs로, Combine은 1012µs에서 237µs로 줄었습니다.

연산 커널의 경우 크기 128의 배치를 크기 64의 두 배치로 분할하면 총 실행 시간이 증가한다는 점에 유의해야 합니다. 따라서 통신에 소요된 시간은 1001µs 감소했지만 총 시간은 771µs만 감소했습니다. 다음 섹션에서 Roofline 모델을 사용하여 그 이유를 설명하겠습니다.

이러한 이유로 마이크로 배치가 항상 성능을 향상시키는 것은 아닙니다.

마이크로 배치를 사용했을 때의 출력 속도 및 노드당 처리량 변화, GPU당 배치 크기에 대해 표시.

위 그림은 배치 크기 4-128에 대해 DispatchOverlap과 비교한 Microbatch의 성능 향상을 보여줍니다. 배치 크기가 32 미만일 때 Microbatch는 성능을 5%-40% 감소시킵니다. 배치 크기가 32 이상일 때 Microbatch는 성능을 10%-35% 향상시킬 수 있습니다.

EP8 vs EP128

이전 그림으로 돌아가 EP8과 EP128 Microbatch를 비교해 보겠습니다. EP8은 총 1802µs가 소요되어 EP128의 1896µs보다 약간 적었습니다. 위에서 언급한 Microbatch로 인한 커널 실행 시간 증가 외에도 주요 차이점은 MoE 연산에 사용되는 GroupGEMM과 두 가지 통신 커널인 Dispatch 및 Combine에 있습니다.

EP8의 GroupGEMM은 555µs가 소요된 반면 EP128의 GroupGEMM은 270µs가 소요되어 절반으로 줄었습니다. 이것이 다중 노드 배포의 핵심 장점입니다.

불행히도 통신에 소요된 시간은 213µs 증가하여 GroupGEMM의 장점을 크게 상쇄했습니다. 당사 통신 커널에 대한 별도의 성능 테스트에서 이 커널들은 Infiniband 대역폭의 절반만 달성할 수 있음을 확인했습니다. 앞으로도 통신 커널을 지속적으로 최적화할 예정입니다.

상당히 뒤처지는 또 다른 커널은 GEMM입니다. Microbatch는 GEMM을 95µs 증가시켰습니다. 아래 Roofline 섹션에서 GEMM을 더 심층적으로 분석하겠습니다. 현재 GEMM 구현은 아직 최적의 성능을 달성하지 못했다고 판단하고 있습니다.

Roofline

Roofline 모델은 커널 성능을 분석하기 위한 좋은 도구입니다. 가로축은 연산 강도로, FLOP와 메모리 I/O 바이트의 비율입니다. 가로축 값은 커널의 의미론에서 직접 계산할 수 있습니다. 세로축은 달성된 성능을 나타내며, FLOP를 벤치마크 지연 시간으로 나누어 계산합니다.

커널 성능의 이론적 상한선은 GPU 사양에 의해 직접 결정됩니다. H100의 FP8 최대 성능은 1979 TFLOP/s이며, Roofline 모델에서 수평선으로 표시됩니다. H100의 메모리 대역폭은 3.35 TB/s이며, 원점을 지나는 선의 기울기로 표시됩니다. 이 두 선은 각각 연산 제한 커널과 메모리 제한 커널에 대한 성능 한계를 제공합니다.

아래에서는 GroupGEMM 및 GEMM 커널의 성능에 대해 논의합니다.

GroupGEMM

MoE의 GroupGEMM 커널은 다음과 같은 연산을 수행합니다. 총 g개의 그룹이 있고, i번째 그룹은 m_i개의 토큰을 가지고 있으며 [m_i, k] x [k, n] -> [m_i, n]의 행렬 곱셈을 수행합니다. 성능 테스트에서 각 그룹의 토큰 수는 m_i = m으로 동일하다고 가정합니다. 그러면 GroupGEMM의 FLOP 수는 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을 계산할 수 있습니다.

당사는 성능 테스트를 위해 DeepGEMM의 GroupGEMM 구현을 사용했습니다. 테스트 포인트는 TP1 및 배치 크기 1-128을 사용하는 EP8, EP16, EP32, EP64, EP128 구성의 조합을 다루었습니다.

컴퓨트 및 메모리 대역폭 로프라인에 대한 상대적 GroupGEMM 성능.

위 그림은 다양한 EP 구성 하의 GroupGEMM에 대한 Roofline 모델을 보여줍니다. 서로 다른 EP는 서로 다른 그룹 수에 해당합니다. 그림은 성능 선이 거의 겹치는 것을 보여주며, 이는 GroupGEMM 성능이 총 토큰 수(g * m)에 의해 주로 결정됨을 나타냅니다.

별 표시는 각 EP 구성에 대해 GPU당 배치 크기가 128인 데이터 포인트를 나타냅니다. 이 별 표시된 데이터 포인트를 비교하면 EP가 증가함에 따라(그리고 DP가 동기적으로 증가함에 따라) 전문가당 토큰 수 m도 증가함을 알 수 있습니다. EP8에서는 m=128이지만 EP128에서는 m=2048입니다.

m이 증가하면 연산 강도도 증가합니다. 대부분의 구성에서 GroupGEMM은 메모리 대역폭에 의해 제한되므로 m을 늘리면 성능이 향상됩니다.

GEMM

GEMM 커널은 Q/K/V/O 투영과 같은 모델의 Linear 투영에 해당합니다. [m, k] x [k, n] -> [m, n] 행렬 곱셈의 경우 FLOP 수는 2 * m * k * n이고 메모리 I/O 바이트는 m * k + n * k + m * n입니다. 배치 크기 1-128에 대한 지연 시간도 테스트할 수 있습니다.

컴퓨트 및 메모리 대역폭 로프라인에 대한 상대적 GEMM 성능.

위 그림은 다양한 EP 구성 하의 GEMM에 대한 Roofline 모델을 보여줍니다. GEMM 성능이 메모리 대역폭에 의해 제한됨을 알 수 있습니다. 배치 크기가 커질수록 연산 강도가 높아져 성능이 향상됩니다.

Microbatch

마이크로 배칭을 사용할 때는 배치를 균등하게 두 부분으로 나눕니다. 위의 두 그림에서 m이 m/2가 되면 행렬 곱셈의 효율성이 감소함을 알 수 있습니다. 따라서 크기가 m/2인 행렬 곱셈을 두 번 실행하는 것이 크기가 m인 행렬 곱셈을 한 번 실행하는 것보다 오래 걸립니다.

다중 토큰 예측

본 게시글 전반에서 당사는 추측 디코딩을 위한 MTP(Multi-Token Prediction) 사용을 가정했습니다. MTP는 요청당 쿼리 길이를 1에서 2로 변경합니다. 행렬 곱셈의 경우 이는 m을 m * 2로 변경하여 행렬 곱셈 효율성을 높이는 것과 같습니다. 반면 MLA에 대한 Roofline 모델을 그리면 쿼리 길이를 늘리면 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에서 사용된 SiLU 활성화 함수는 CUDA 그래프, 블록 양자화 및 동적으로 라우팅된 토큰 수를 지원하기 위해 상당한 변경이 필요했습니다. 블록 양자화는 수평적 축소를 도입하므로 문제가 될 수 있지만, 커널은 이미 은닉 차원을 따라 활성화를 1024 요소 블록으로 청크 처리했습니다. 한 블록 내에서 양자화할 텐서는 최댓값을 계산하기 위해 128 블록으로 추가 청크 처리되었으며, Triton은 효율적인 cross-warp 최대 축소를 생성하여 오버헤드를 최소화했습니다.

CUDA 그래프 하에서 MoE 라우팅을 지원하기 위해 커널은 토큰 수의 상한선을 보유하기 위해 할당된 버퍼 크기를 기준으로 작업을 예약하는 대신, 전문가당 토큰 수를 나타내는 라우팅 정보를 인식해야 합니다. 입력 텐서 차원을 기준으로 문제를 나눌 수 없으므로, 라우팅 정보를 읽어 채워진 토큰 수를 결정하고 활성화 처리 작업을 동적으로 분할하는 고정된 수의 지속적 커널을 실행합니다.

당사는 이미 커널 중 일부를 FlashInfer 프로젝트에 업스트림했으며 향후 더 많은 코드를 오픈 소스로 공개할 예정입니다.

MLA 레이어

당사는 MLA 연산을 위해 FlashInfer를 사용합니다. FlashInfer는 유연한 페이지 테이블 설정과 매우 높은 성능을 지원합니다.

당사는 q_a_proj와 kv_a_proj를 단일 qkv_a_proj로 융합했습니다. 지연 시간은 15.4 µs + 14.8 µs = 30.2 µs에서 16.7 µs로 감소했습니다.

당사는 kv_b_proj를 두 개의 행렬 k_b_proj 및 v_b_proj로 분해했습니다. 이 두 행렬과 관련된 연산을 위해 FP8 블록 양자화 BMM 커널을 작성했습니다.

Cuda Graph

Cuda Graph는 커널 시작 오버헤드를 크게 줄일 수 있으며, 이는 성능에 매우 중요합니다. 당사는 각 배치 크기에 대해 Cuda Graph를 생성합니다.

AllToAll 커널을 개발하기 전에 당사는 AllToAll 통신을 위해 torch.all_to_all_single()을 사용했습니다. 이 작업은 모든 GPU가 동일한 배치 크기를 사용해야 합니다. 그러나 서로 다른 DP 그룹은 서로 다른 배치 크기로 실행될 수 있습니다.

all_to_all_single()이 서로 다른 배치 크기를 사용하는 여러 DP 그룹과 호환되도록 하기 위해 각 모델 실행 전에 allreduce() 작업을 사용하여 모든 DP 그룹 중 최대 배치 크기를 먼저 구했습니다. 그런 다음 모든 DP 그룹이 이 배치 크기를 사용하여 실행하도록 했습니다.

이 접근 방식은 Cuda Graph를 사용할 수 있게 보장하지만 세 가지 단점이 있습니다. 첫째, 추가적인 allreduce() 작업이 필요합니다. 둘째, 배치 크기가 작은 DP 그룹은 강제로 패딩해야 합니다. 셋째, 구현 코드가 복잡해집니다.

자체 AllToAll 커널을 구현한 후에는 모든 GPU가 동일한 배치 크기를 사용할 필요가 없습니다. 따라서 추가적인 allreduce() 작업을 수행하거나 배치 크기를 패딩할 필요가 없습니다.

MoE 라우터

MoE 라우터는 Triton으로 구현되었으며 표준 라이브러리에서 파생된 수정된 정렬을 사용합니다. 이 정렬은 정렬된 요소의 인덱스도 추적합니다. Mixtral 라우팅은 Top-K 그룹이 모든 전문가 그룹과 동일한 DeepSeek 라우트의 특수한 경우이므로 구현은 모든 MoE 모델에서 공유됩니다. 희소 커널은 Top-K 인덱스와 점수를 직접 소비하는 반면, all-to-all에 의존하는 밀집 dispatch/combine 방식은 토큰 기반이 아닌 전문가별로 라우팅 정보를 집계해야 합니다.

향후 계획

향후 계획으로 당사는 DeepSeek 모델의 성능을 더욱 최적화할 예정입니다.

가장 중요한 다음 최적화는 Prefill 분리입니다. DeepSeek-V3/R1 모델의 Prefill 단계와 Decode 단계는 계산 특성이 매우 다릅니다. 두 단계 모두 서로 다른 최적화 전략과 배포 계획을 사용할 수 있습니다.

MLA 레이어의 경우 Decode 단계에서는 행렬 흡수를 사용하여 MLA 연산의 FLOP 수를 줄입니다. Prefill 단계에서는 먼저 잠재 벡터를 K/V 스페이스로 투영한 다음 MHA(Multi-Head Attention) 형식으로 계산하는 것이 더 나은 성능을 보입니다.

Prefill과 Decode가 동일한 GPU에서 실행되는 경우 Prefill이 Decode 출력 속도에 미치는 영향을 줄이기 위해 일반적으로 청크 기반 Prefill을 사용하여 쿼리를 여러 청크로 나눕니다. KV 캐시가 잠재 벡터를 저장하기 때문에 MLA를 MHA 형식으로 변환하기 어렵습니다.

MoE 레이어의 경우 Decode 단계에서는 전문가당 입력 토큰 수를 늘려 GroupGEMM 성능을 향상시키기 위해 가능한 한 큰 EP와 DP를 사용합니다. Prefill 단계에서는 이미 토큰 수가 충분히 많기 때문에 GroupGEMM이 이미 연산 제한 상태입니다. 따라서 Prefill에는 더 작은 EP와 DP를 사용할 수 있습니다.

Prefill과 Decode가 동일한 GPU에서 실행되는 경우 DP 그룹 중 하나라도 Prefill을 수행 중이면 모든 GPU의 MoE 레이어 지연 시간이 증가하여 Decode 출력 속도에 상당한 영향을 미칩니다.

Prefill 분리 외에도 다음 측면을 최적화할 계획입니다.

AllToAll 성능: 현재 당사의 AllToAll 커널은 Infiniband 대역폭의 1/3만 달성할 수 있습니다. 앞으로 이 커널을 지속적으로 최적화할 예정입니다.

EAGLE 스타일 추측 디코딩: 위 데이터에서 당사는 추측 디코딩을 사용하여 1개의 토큰을 예측한다고 가정했습니다. EAGLE은 트리 구조를 사용하여 여러 토큰을 예측하고 수락 길이를 개선할 수 있으며, 이는 출력 속도를 크게 높일 수 있습니다.

GEMM 커널: 앞서 보여드린 Roofline 모델에서 GEMM 커널의 효율성이 이론적 한계와는 아직 거리가 멀다는 것을 알 수 있습니다. 당사는 이 커널을 지속적으로 최적화할 것입니다.

GB200 NVL72: NVIDIA의 최신 GB200 NVL72 솔루션에서는 72개의 Blackwell GPU가 고속 NVLink를 통해 상호 연결됩니다. MoE 아키텍처 모델의 경우 이는 매우 큰 기회이자 도전 과제입니다.

결론

DeepSeek MoE 모델의 다중 노드 배포는 기존 밀집 LLM으로는 불가능한 처리량과 지연 시간의 동시 개선을 달성합니다. 전문가를 더 많은 GPU에 분산함으로써 장치당 메모리 대역폭 압력을 줄여 더 빠른 처리와 더 높은 시스템 처리량을 가능하게 합니다. 당사 실험에 따르면 EP128 구성은 단일 노드 배포 대비 동일한 출력 속도에서 최대 5배 더 높은 처리량을 달성했습니다.

마이크로 배칭과 같은 연산-통신 중첩 기술은 다중 노드 통신 오버헤드를 크게 줄이며, 당사의 구현은 최대 40%의 속도 향상을 보였습니다. 당사의 사용자 지정 AllToAll 통신 커널과 최적화된 커널 구현을 통해 6,710억 개의 매개변수 모델을 효율적으로 배포할 수 있게 되었습니다.

MoE 아키텍처가 그 역량으로 인기를 얻으면서 이러한 배포 전략은 해당 모델을 효율적으로 확장하는 데 귀중한 통찰력을 제공합니다.

참고 문헌

DeepSeek-V3 기술 보고서

DeepSeek-V3/R1 추론 시스템 개요

Megatron-LM: 모델 병렬성을 사용한 수십억 개 매개변수 언어 모델 학습

EAGLE: 추측 샘플링은 특징 불확실성에 대한 재고를 요구함

인용

BibTeX
@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}
}