분산된 프롬프트 처리를 위한 Red와 Green 팀의 결합
요약
로컬 에이전트 코딩 시 발생하는 긴 컨텍스트의 프롬프트 처리(PP) 성능 저하를 해결하기 위해, DGX Spark를 프리필(Prefill) 전용으로, Strix Halo를 디코드(Decode) 전용으로 사용하는 분산 파이프라인 구축 사례를 소개합니다.
핵심 포인트
- 에이전트 루프의 긴 컨텍스트 처리를 위해 PP와 TG의 분리(Disaggregation)가 필요함
- DGX Spark의 연산력을 토큰 생성(TG) 대신 프리필(PP)에 집중하여 효율 극대화
- Strix Halo와 DGX를 결합하여 분산 PP-to-TG 파이프라인 구축 성공
- 디코드 단계는 연산력보다 메모리 대역폭에 의존하므로 기기 간 성능 차이가 적음
여러분 중 일부는 제가 이곳에 올린 이전 게시물들을 보셨을 것입니다. 저는 단일 Strix Halo 박스(Bosgame M5)로 이 모든 여정을 시작했습니다. OpenCode를 이용한 로컬 에이전트 코딩(agentic coding)을 수행할 때, 이 기기는 진정으로 훌륭합니다. 충분한 통합 메모리(unified memory)를 갖추고 있고 토큰 생성(token generation)도 안정적이지만, 컨텍스트(context)가 길어지면 프롬프트 처리(prompt processing, PP) 성능이 심하게 저하됩니다. OpenCode와 같은 에이전트 루프(agentic loops)는 모든 도구 호출(tool call) 시마다 컨텍스트의 일부를 다시 불러와야 하므로 PP에 매우 가혹하며, 이 비용을 지속적으로 다시 지불해야 합니다.
전용 매트릭스 엔진(matrix engine)이 도움이 될 것이라 생각하여 PP를 NPU로 오프로딩(offloading)해 보았습니다. 하지만 효과가 없었습니다. NPU의 PP는 실제로 iGPU보다 더 나빴습니다. 결국 iGPU PP를 사용하게 되었지만, 높은 컨텍스트에서는 충분히 빠르지 않습니다.
호기심(그리고 제 업무와 관련이 있기 때문)에 DGX Spark를 하나 장만했습니다. 예전에 EXO를 통해 DGX Spark와 Mac을 결합한 분산된 PP/TG(prefill/token generation) 설정을 본 기억이 났고, DGX 단독 수치를 확인하며 그 PP 성능이 얼마나 강력한지 깨닫자 아이디어는 명확해졌습니다. 만약 DGX가 프리필(prefill)을 담당하고, 이미 충분한 메모리와 괜찮은 TG 성능을 가진 Strix Halo가 디코드(decode)를 담당한다면 어떨까? 하는 점이었습니다.
그래서 Claude Code를 llama.cpp 소스에 풀어놓았고, 몇 시간의 반복 작업 끝에 두 기기 모두에서 Qwen 3.5 122B (MTP) GGUF를 실행하는 작동 가능한 분산 PP-to-TG 파이프라인을 구축했습니다. 아래는 이 방식이 왜 작동하는지 이해하는 데 실제로 의미 있는 순서대로 정리한 벤치마크입니다. 먼저 첫 번째 토큰 생성(이것이 문제가 아님을 보여주기 위해), 그다음 분산 프리필(실제 이점과 네트워크 속도의 역할을 보여주기 위해), 마지막으로 동시 다중 요청 서빙(여러 에이전트가 동시에 실행되는 실제 시나리오) 순입니다.
- 토큰 생성: DGX와 Strix는 기본적으로 대등함
이것은 직관에 어긋나기 때문에 가장 먼저 확립해 둘 가치가 있는 부분입니다.
DGX Spark는 훨씬 더 비싸고 "진지한" 장비이지만, 디코드 (decode) 단계에서는 거의 차이가 없습니다.
Context | DGX TG t/s | Strix TG t/s | DGX advantage
512 | 23.5 | 20.5 | +15%
1k | 23.4 | 20.5 | +14%
2k | 23.3 | 20.4 | +14%
32k | 21.2 | 18.8 | +13%
64k | 19.7 | 17.5 | +13%
차이는 단 13~15%에 불과하며, 컨텍스트 (context) 길이에 따라 거의 변하지 않습니다. 이는 디코드 (decode)가 메모리 대역폭 제한 (memory-bandwidth bound)을 받기 때문이며, 두 머신은 이 모델에 대해 유사한 유효 대역폭 (effective bandwidth)을 가지고 있습니다. DGX의 훨씬 더 큰 연산 (compute) 우위는 여기서 전혀 나타나지 않으며, 토큰 생성 (TG)에 낭비되고 있습니다.
이것이 바로 분리 (disaggregation)를 정당화하는 이유입니다. 만약 TG가 별 차이가 없다면, DGX의 연산 예산을 토큰 생성에 낭비하지 마십시오. 실제로 중요한 곳인 프리필 (PP, prefill)에 투자하십시오.
- 분리된 단일 요청 벤치마크: Strix Halo 단독 실행 vs. DGX PP에서 Strix TG로의 연결
이 표가 핵심 결과입니다. 왼쪽 절반은 Strix Halo가 단독으로 엔드 투 엔드 (end to end) 실행되는 경우입니다. 오른쪽 절반은 DGX Spark가 프리필 (prefill)을 수행하고, KV 캐시 (KV cache)를 직렬화하여 네트워크를 통해 Strix Halo로 전송하면, Strix Halo가 이를 복구하여 디코드 (decode)를 수행하는 경우입니다.
Tokens | Strix PP t/s | Strix PP ms | Strix TG t/s | Strix TG ms | Strix total ms | DGX ms | Xfer ms | PP plus Xfer ms | KV MB | Decode ms | Disagg TG t/s | Disagg TG ms | Disagg total ms | Speedup
512 | 275.4 | 1860 | 20.5 | 6240 | 8100 | 1121 | 538 | 1659 | 161.4 | 340 | 20.5 | 6240 | 1999 | 4.1x
1024 | 293.3 | 3492 | 20.5 | 6256 | 9748 | 1737 | 578 | 2315 | 173.4 | 356 | 20.5 | 6256 | 2671 | 3.6x
2047 | 300.1 | 6822 | 20.4 | 6276 | 13098 | 2927 | 658 | 3585 | 197.4 | 375 | 20.4 | 6276 | 3960 | 3.3x
4031 | 306.6 | 13148 | 20.2 | 6338 | 19486 | 5244 | 813 | 6057 | 243.9 | 446 | 20.2 | 6338 | 6503 | 3.0x
7999 | 299.3 | 26726 | 19.7 | 6494 | 33220 | 10065 | 1123 | 11188 | 337.0 | 644 | 19.7 | 6494 | 11832 | 2.8x
15935 | 281.8 | 56544 | 19.4 | 6593 | 63137 | 20090 | 1744 | 21834 | 523.1 | 880 | 19.4 | 6593 | 22714 | 2.8x
31807 | 244.7 | 129994 | 18.8 | 6791 | 136785 | 40855 | 2985 | 43840 | 895.4 | 1284 | 18.8 | 6791 | 45124 | 3.0x
63551 | 195.6 | 324851 | 17.5 | 7317 | 332168 | 86424 | 5467 | 91891 | 1640.0 | 2184 | 17.5 | 7317 | 94075 | 3.5x
127039 | 140.0 | 907650 | 15.3 | 8345 | 915995 | 196092 | 10431 | 206523 | 3129.2 | 4014 | 15.3 | 8345 | 210537 | 4.4x
여기서 보여주는 결과는 매우 극명합니다.
Strix Halo 자체의 PP (Prefill) 성능은 짧은 컨텍스트(short context)에서의 275 t/s에서 127k 토큰에서는 140 t/s까지 떨어집니다. 단순히 속도가 느려지는 것뿐만 아니라, 컨텍스트가 길어질수록 성능이 저하되는데, 이는 긴 에이전트 세션 (agentic sessions)을 망가뜨리는 바로 그 실패 모드 (failure mode)입니다. DGX는 동일한 범위에서 거의 영향을 받지 않습니다. 127k 토큰에 도달했을 때, 분산된 경로 (disaggregated path)는 프리필 (prefill), 전송 (transfer), 디코드 (decode)를 총 약 210초 만에 완료하는 반면, Strix Halo가 단독으로 수행할 때는 약 916초가 걸립니다. 이것은 미미한 승리가 아니라, 실용적으로 사용할 수 있느냐 아니면 기다리는 동안 커피를 타러 가야 하느냐의 차이입니다.
네트워크 속도의 역할
이 부분은 명시적으로 언급할 가치가 있습니다. 전송 비용 (transfer cost)은 공짜가 아니며, 그 비용이 얼마나 드느냐는 전적으로 두 장치를 무엇으로 연결하느냐에 달려 있기 때문입니다.
제 Bosgame M5 (Strix Halo)에는 2개의 USB4와 2.5G 이더넷 (ethernet)이 있습니다. 저는 DGX Spark에도 USB4/Thunderbolt가 있을 것이라고 가정했습니다. 하지만 그렇지 않았습니다. DGX의 USB-C 포트는 USB 3.2 Gen2이며, 10GbE가 있고, 그 외에 Spark 간 클러스터링 (clustering)을 위해 설계된 빠른 NVIDIA 인터커넥트 (interconnect, ConnectX, 대략 200Gb급)가 있지만, 이는 일반적인 AMD 장치와 통신하기 위한 것이 아닙니다.
저는 USB4 네트워킹 속도를 기대하며 USB-C를 통해 두 장치를 직접 연결해 보았습니다. 하지만 작동하지 않았습니다. 한쪽은 USB4이고 다른 한쪽은 USB 3.2 Gen2이며, USB 3.2가 이론적으로 호스트 간 네트워킹 (host-to-host networking)을 지원함에도 불구하고, DGX의 컨트롤러와 칩셋은 이를 노출하지 않는 것으로 보입니다. 그래서 결국 저는 일반적인 2.5GbE로 연결했고, 위의 모든 수치는 바로 이 환경에서 측정되었습니다.
핵심은 이렇습니다: 2.5GbE는 여기서 한계치에 전혀 미치지 못합니다. 만약 양쪽 모두에 일치하는 USB4 포트(또는 적절한 10/20/40GbE 링크)가 있었다면, 짧은 컨텍스트에서는 연산 (compute) 대비 이미 작지만 긴 컨텍스트에서는 실질적인 문제가 되는 전송 비용은 대부분 사라졌을 것입니다.
동일한 3129.2 MB KV 캐시(KV cache)를 사용하여, 다양한 링크 속도에 따른 127k-토큰 전송 양상은 다음과 같습니다:
| 링크 | 유효 대역폭 (Effective BW) | 전송 시간 (Xfer ms) | PP + 전송 + 연산(Compute) 총합 (ms) |
|---|---|---|---|
| 2.5GbE (실제) | ~300 MB/s | 10,431 | 206,523 |
| 10GbE | ~1.2 GB/s | 2,608 | 198,700 |
| 20GbE | ~2.4 GB/s | 1,304 | 197,396 |
| 40GbE (USB4급) | ~4.8 GB/s | 652 | 196,744 |
| 100GbE | ~12 GB/s | 261 | 196,353 |
약 20GbE를 넘어서면 전송 시간은 기본적으로 노이즈 수준으로 사라지며, 남는 것은 DGX의 순수 연산 시간(약 196초)과 디코딩(decode, 약 4초) 시간뿐입니다. 즉, 2.5GbE만으로도 이 작업을 수행할 가치는 충분하지만, 더 빠른 링크를 사용하지 않음으로써 실제 성능을 제대로 활용하지 못하고 있는 셈입니다. 제대로 된 네트워킹(networking)을 도입한다면, 분산된(disaggregated) 경로 전체가
실제 동시 실행(concurrent run)에서 얻은 가공되지 않은(Raw) TG 수치는 반복적인 벤치마크 프롬프트에서 Qwen3.5가 사고 토큰(thinking tokens)을 폭발적으로 생성함에 따라 왜곡되었습니다(위의 단일 요청 각주와 동일한 문제). 따라서 아래의 하이브리드(hybrid) 열은 부풀려진 가공되지 않은 수치 대신 실제 독립형(standalone) TG 타이밍을 대체하여 사용합니다:
토큰 수 | Strix 독립형 (PP+TG) | DGX 독립형 (PP+TG) | 독립형, 마지막 사용자 완료 | 독립형, 첫 번째 사용자 완료 | 하이브리드 동시 실행, 마지막 사용자 완료~ | 하이브리드 동시 실행, 첫 번째 사용자 완료~
512 | 8,100 | 6,195 | 8,100 | 6,195 | 8,787 | 8,787
1024 | 9,748 | 6,793 | 9,748 | 6,793 | 9,177 | 9,177
2047 | 13,098 | 7,940 | 13,098 | 7,940 | 11,770 | 11,770
4031 | 19,486 | 10,197 | 19,486 | 10,197 | 17,818 | 17,818
7999 | 33,220 | 14,742 | 33,220 | 14,742 | 18,914 | 18,914
15935 | 63,137 | 23,996 | 63,137 | 23,996 | 30,161 | 30,161
31807 | 136,785 | 43,752 | 136,785 | 43,752 | 72,807 | 72,807
63551 | 332,168 | 87,039 | 332,168 | 87,039 | 186,382 | 186,382
127039 | 915,995 | 191,701 | 915,995 | 191,701 | 303,164 | 303,164
~ 하이브리드 실제 TG는 측정된 동시 실행의 마지막_ms에 (실제 Strix TG에서 Qwen3.5 사고 토큰 아티팩트를 뺀 값)을 더한 것으로 추정되었습니다. 이는 DGX가 두 PP 요청을 동시에 배치(batch) 처리하기 때문입니다.
판결:
512 토큰 이하에서는 독립형이 근소한 차이(약 8%)로 승리합니다. 해당 길이에서는 Strix 자체의 PP가 충분히 빠르기 때문에, 하이브리드를 위해 KV 전송 오버헤드(KV-transfer overhead)를 지불할 가치가 없습니다.
약 1k 토큰을 넘어서면 하이브리드가 앞서나가기 시작하며 그 격차는 빠르게 벌어집니다. 128k 컨텍스트(context)에서 하이브리드는 두 요청을 모두 약 303초 만에 완료하는 반면, 독립형의 경우 Strix에 할당된 요청은 약 916초가 걸려 최악의 경우 지연 시간(latency)이 약 3배 개선됩니다.
그 이유는 섹션 2에서 언급한 것과 동일합니다. 긴 컨텍스트에서 성능이 무너지는 것은 바로 Strix의 PP입니다. 독립형 모드에서는 Strix에 할당된 요청이 해당 성능 저하를 그대로 겪게 됩니다. 하이브리드 모드에서는 DGX가 두 요청에 걸쳐 배치 처리하더라도 모든 PP 작업을 처리하며, Strix는 오직 TG만 수행하게 되는데 이는 Strix가 잘 수행하는 작업입니다.
핵심 요약 (Takeaway)
로컬 에이전트 코딩 (agentic coding)을 위해 단일 Strix Halo를 실행하는 경우, 실제 병목 현상은 메모리나 TG (Token Generation)가 아니라 긴 컨텍스트 (long context)에서의 PP (Prefill)입니다. DGX Spark를 추가하고 분리 (disaggregating)하여, DGX가 프리필 (prefill)을 수행하고 Strix(및 DGX 자체의 여유 디코드 용량)가 토큰 생성 (token generation)을 수행하도록 구성하는 것은 단일 요청뿐만 아니라, OpenCode와 같은 도구들이 실제로 사용되는 방식인 동시 다중 에이전트 (concurrent multi-agent) 케이스에서도 진정으로 훌륭한 아키텍처임이 드러났습니다. 교차점(crossover point)은 대략 "매우 짧은 프롬프트를 넘어서는 모든 경우"이며, 에이전트 코딩의 경우 이는 기본적으로 항상 해당됩니다.
이야기의 나머지 절반은 네트워크 링크입니다. DGX Spark의 USB-C 포트가 USB4/TB4가 아닌 USB 3.2 Gen2로 밝혀지면서 두 장치 간의 직접적인 USB 연결이 성사되지 않아, 현재 저는 2.5GbE에 머물러 있습니다. 그럼에도 불구하고 2.5GbE는 실제적인 컨텍스트 길이(context length)에서 명확한 승리를 거두기에 이미 충분히 좋지만, 더 빠른 링크를 사용할 수 있다면 유의미한 여유 공간(headroom)이 남아 있습니다. 약 20GbE를 넘어서면 전송 비용은 무의미해지며, 단순히 DGX의 순수 연산 시간(raw compute time)에 의해 제한되기 때문입니다.
관심이 있으시다면 질문에 답변하거나 원시 벤치마크 하네스 (raw benchmark harness)를 더 공유해 드릴 용의가 있습니다.
(또한, 내용을 더 깔끔하게 만들기 위해 AI가 제 문장을 다시 쓰게 되었습니다)
submitted by /u/reujea0 to r/LocalLLaMA
[link] [comments]
AI 자동 생성 콘텐츠
본 콘텐츠는 r/OpenAI Codex (search)의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기