두 개의 96GB Ascend 카드로 Qwen3.8-flash-next 구동하기: 하드웨어 노트, vLLM 작업 및 벤치마크 결과
요약
본 글은 Huawei Atlas 300I Duo 카드를 활용하여 Qwen3.8 Flash-Next 모델을 구동한 경험과 하드웨어 노하우를 공유합니다. 이 시스템은 두 개의 96GB 카드(실제로는 네 개의 48GB 레벨)로 구성되어 있으며, vLLM 최적화와 소프트웨어 스택 개선을 통해 높은 추론 성능(최대 61 tok/s)을 달성했음을 보여줍니다.
핵심 포인트
- Atlas 300I Duo 카드는 두 개의 가속기 SoC를 포함하며, 메모리는 LPDDR4X입니다.
- 모델 병렬화 시, 이 장치를 하나의 96GB GPU가 아닌 네 개의 48GB 레벨로 인식하는 것이 중요합니다.
- 성능 향상은 하드웨어 자체보다 소프트웨어 스택(드라이버, 아키텍처 지원, 비동기 상태 전이) 최적화에 달려 있습니다.
- HCCL collectives를 사용하여 모든 가속기 칩에 걸쳐 텐서 및 전문가 소유권을 명시적으로 매핑해야 합니다.
저는 Huawei Atlas 300I Duo 카드 두 개를 중심으로 다소 특이한 로컬 추론 머신을 구축해 왔습니다. 이 카드는 각각 96GB의 장치 메모리를 가진 비교적 저렴하고 수동식(passive)의 듀얼-가속기 PCIe 카드입니다. 또한, CUDA와 바로 대체할 수 있는 제품은 절대 아닙니다. 지난 2주 동안 Qwen3.8 Flash-Next를 처음 다루었을 때, 모델이 종종 일관성이 없었고 초당 생성 토큰 수가 1개 정도에 머물렀습니다. 일부 실행에서는 그보다 낮은 경우도 있었습니다. 하지만 오늘 같은 두 개의 카드 장비가 단일 요청에 대해 약 30 tok/s의 일관된 출력을 내고, 짧은 디코딩 벤치마크에서 네 가지 동시성(four-way concurrency)으로 집계하면 약 61 tok/s를 보여주고 있습니다. 또한 전체 198개 문항으로 구성된 GPQA Diamond 세트도 모두 완료했습니다. 이 게시물은 이 카드들에 대한 가이드의 시작입니다: 카드가 물리적으로 무엇인지, 제가 어떻게 냉각시키는지, '96 GB'가 실제로 무엇을 의미하는지, vLLM과 vLLM Ascend에서 무엇을 변경했는지, 어떤 최적화가 실제로 중요했는지, 그리고 아직 해결되지 않은 문제는 무엇인지에 대해 다룰 것입니다. 요약하자면 하드웨어는 충분한 능력을 갖추고 있습니다. 제 작업은 주로 소프트웨어 스택(ubuntu-26.04 드라이버 지원, 모델 아키텍처 지원, 메모리 레이아웃, 사용자 지정 연산자(custom operators), 그리고 모든 비동기 상태 전이(asynchronous state transition)를 정확하게 처리하는 것)에 집중되었습니다.
하드웨어: 하나의 카드가 실제로는 두 개의 장치
현재 제 머신에는 Atlas 300I Duo 카드 두 개가 있으며, 이는 네 개의 Ascend 310P3 장치로 인식됩니다.
| 구분 | 현재 시스템 / 계획 시스템 |
|---|---|
| 물리적 카드 수 | 2 / 3 |
| Ascend 장치/NPU/AI CPU: | 4 / 6 |
| 명판 장치 메모리: | 192 GB / 288 GB |
| 이 구성을 통한 근사 실행 가시 메모리: | 172 GiB / 258 GiB |
| 결합 최대 가속기-보드 전력: | 300 W / 450 W |
각 카드는 두 개의 가속기 SoC와 총 96 GB의 LPDDR4X를 가지고 있으며, 이는 각 칩에 로컬로 48 GB씩 할당됩니다. 이것은 하나의 통합된 96 GB 할당이 아닙니다. 단일 48 GB 장치에 들어가지 않는 모델이라도 여전히 텐서(tensor), 전문가(expert), 파이프라인(pipeline) 또는 다른 형태의 모델 병렬화가 필요합니다. 이 카드는 PCIe Gen4 x16, 풀-하이트/풀-렝스이며 놀라울 정도로 얇은 싱글 슬롯 디자인입니다. Huawei는 이를 총 408 GB/s의 메모리 대역폭과 최대 보드 전력 150 W로 평가합니다.
공식 사양은 여기에서 확인할 수 있습니다 (https://support.huawei.com/enterprise/en/doc/EDOC1100285916?section=j00e). 또한, 많은 가속기 소프트웨어에서 일반적인 'HBM' 용어를 사용함에도 불구하고, 이 카드들의 메모리는 LPDDR4X입니다. 이 두 칩-당-카드 레이아웃이 중요합니다. 모델 내부 통신은 여전히 분산 런타임(distributed runtime)을 통해 이루어지며, 메모리는 각 레벨(rank)에 국한됩니다. 저는 HCCL collectives를 사용하고 모든 네 개의 칩에 걸쳐 텐서 및 전문가 소유권을 명시적으로 매핑합니다. 이 장치를 두 개의 96GB GPU로 생각하는 것보다 네 개의 48GB 레벨로 생각하는 것이 훨씬 유용합니다. https://reddit.com/link/1wvt1m4/video/7rju7qbrw1th1/player 수동 냉각(Passive cooling)은 치명적인 결함이 아닙니다. 이 카드들은 큰 방열판과 온보드 팬이 없습니다. 서버 공기 흐름을 위해 설계되었으므로, 일반 워크스테이션에 넣고 후면 케이스 팬이 해결해 주기를 바라는 것은 나쁜 계획입니다. 방열판과 히트파이프 배열을 보고 싶다면 유용한 분해 영상(https://videocardz.com/newz/huawei-atlas-300i-dual-ai-gpu-with-96gb-memory-worth-1400-has-been-taken-apart)이 있습니다. 저는 이 카드들에 직접적이고 대용량의 공기 흐름을 제공하고 실내를 AC/열펌프 냉각으로 운영합니다. 실제 다중 시간 모델 부하(multi-hour model loads)에서도 카드는 문제없이 지속적으로 작동할 수 있습니다. 제가 기록한 Qwen 실행에서 최고 장치 온도는 일반적으로 72–78 °C였습니다. 제 감시견 제한(watchdog limit)은 96 °C이며, 카드들은 이 온도에 근접하지 않았습니다. 따라서 저는 또 다른 수동 카드를 추가하는 것에 대해 신경 쓰지 않을 것입니다. 실제 체크리스트는 다음과 같이 평범합니다: • 방열판 핀을 통해 공기 흐름이 막히지 않도록 유지합니다. • 케이스 팬이 충분한 정압(static pressure)을 갖는지 확인합니다. • 카드당 150W의 보드 전력과 나머지 호스트 전력을 예산에 포함합니다. • 열을 재순환시키기보다 실내에서 배출시킵니다. • 유휴 상태 측정값만 신뢰하기보다는 긴 프리필(prefill), 디코드(decode), 동시성 테스트 동안 온도를 기록합니다. 수동이라는 것이 저전력 또는 자가 냉각을 의미하는 것은 아닙니다. 이는 케이스와 실내가 냉각 시스템임을 의미합니다.
이 부분이 처리되면, 이 카드들은 저에게 일반적인 150W 서버 카드처럼 작동했습니다. 참고: 이 카드들을 가장 뜨겁게 만드는 것은 RAM에서 무언가를 로드하거나 이동시키는 것입니다. NPU가 최대 활용률로 작동할 때도 대용량 메모리 할당보다 더 시원합니다. 저희는 모델 서빙 코드 경로를 최적화할 때 이것을 염두에 둡니다.
ECC(오류 수정 코드), 명판 메모리, 그리고 실제로 사용 가능한 용량이 있습니다. 제 카드는 기본적으로 ECC가 활성화되어 왔습니다. 저는 장치 메모리를 확보하기 위해 이를 비활성화했습니다. 이곳은 추론 및 개발용 박스이며, 저는 여기서 ECC 보호보다 용량을 의식적으로 선호합니다. 이것은 신뢰성 트레이드오프일 뿐, 보편적인 권장 사항은 아닙니다. ECC를 비활성화하더라도 펌웨어, 런타임, 통신 버퍼, 그래프 캡처, 작업 공간(workspaces), 할당자 예약 등이 메모리를 소비합니다. 실제로는 소프트웨어가 48GB 칩당 약 43GiB를 사용합니다. 따라서 네 개의 칩은 약 172GiB의 유용한 총 용량을 제공하지만, 여전히 네 개의 분리된 로컬 풀입니다. 정확한 남는 용량은 CANN 빌드 및 실행 구성에 따라 달라집니다. 이러한 구분이 거의 모든 모델 결정에 영향을 미쳤습니다. 질문은 단순히 “체크포인트 전체가 192GB에 들어갈까?”가 아닙니다. “각 랭크의 가중치 샤드(weight shard), 순환 상태(recurrent state), KV/캐시 할당, 그래프 캡처, 집합 작업 공간(collective workspace), 그리고 최악의 경우 임시 할당이 자체적인 43GiB에 들어갈까?”입니다.
제가 vLLM뿐만 아니라 vLLM Ascend를 포크한 이유
공개된 작업은 OpenSensor vLLM Ascend 포크(https://github.com/opensensor/vllm-ascend)와 페어링된 vLLM 포크(https://github.com/opensensor/vllm)에 있습니다. 저는 양쪽 모두가 필요했습니다. 왜냐하면 이것이 단순히 누락된 장치 커널 문제가 아니었기 때문입니다. 현재 제가 이 포크들을 개발하는 유일한 사람입니다. 오늘날 소프트웨어 버스 팩터(software bus factor)는 1입니다. 많은 진전을 이루었지만, 빠르게 움직이는 1인 포크가 NVIDIA의 메인라인 vLLM의 성숙도, 테스트 커버리지 또는 지원 깊이와 혼동되어서는 안 됩니다.
또한 기이한 도구 문제에 직면했습니다. 세션에서 Claude는 이 아키텍처에 대한 프롬프트에 대해 반복적으로 참여를 거부했는데, 그 이유는 카드가 중국의 Huawei 하드웨어였기 때문입니다. 이는 제한된 애플리케이션을 구축해 달라는 요청이 아니라, 서빙(serving), 샤딩(sharding), 냉각(cooling), 성능에 관한 평범한 엔지니어링 논의였습니다. 저는 모든 Claude 버전이나 계정이 동일하게 작동할 것이라고 주장하기보다는 저의 직접적인 경험을 설명하고 있지만, 이로 인해 Claude는 이 프로젝트를 위한 개발 보조 도구로서 신뢰성이 떨어졌습니다. 정치적으로 어떤 생각을 하든 간에, 이 하드웨어 주변에서 도구를 선택할 때 실제로 존재하는 실질적인 제약 사항입니다. Qwen3.8 Flash-Next는 MoE 라우팅(MoE routing), Gated DeltaNet 순환 레이어(Gated DeltaNet recurrent layers), 희소 이차 어텐션 레이어(sparse quadratic-attention layers), 패킹된 저비트 전문가(packed low-bit experts), 긴 컨텍스트, 그리고 MTP 초안 모델을 결합합니다. 이 복잡한 모델 통합을 지원하기 위해 v1 러너, 캐시 계정(cache accounting), 스케줄링(scheduling), 그래프 캡처(graph capture), 분산 상태(distributed state), 모델 로딩(model loading), 그리고 Ascend 전용 연산자(Ascend-specific operators)가 필요했습니다. 현재 개발 스프린트는 거의 연속적인 구동 및 최적화 작업으로 약 2주 반이 지났으며, 수백 개의 포크 커밋, 반복적인 전체 체크포인트 로드, 프로파일러 캡처, 연산자 마이크로벤치마크, 그리고 몇 시간에 걸친 품질 테스트가 진행되었습니다. 이것은 하나의 마법 같은 커널 패치가 아니었습니다. Qwen을 일관성 없는 ~1 tok/s에서 현재의 수준으로 끌어올린 것은 아키텍처적 변화들이었습니다. 속도를 높이기 전에 하이브리드 모델이 정확하도록 만드세요. 초기 모델은 토큰을 생성할 수 있었지만, 생성이 정확성을 테스트하는 것은 아니었습니다. 저는 프로덕션 환경의 기하학(geometry)에서만 나타나는 실패들을 발견했습니다. 잘못된 Gated DeltaNet 게이트-벡터 처리, 순환 상태 정밀도 및 라이프사이클 문제, 불완전한 희소 어텐션 점수 폭(sparse-attention score width), 그리고 호스트 연산자 API와 설치된 커널 패키지 간의 불일치 등이 그것입니다. 특히 까다로웠던 GDN 문제는 작은 헤드 테스트에서는 괜찮아 보였지만, 실제 36개의 순환 레이어에 걸쳐 상태 오류를 누적시키며 일관성 없는 텍스트를 생성했습니다.
재귀 상태를 FP32로 유지하고 프로덕션 환경의 데이터 이동 방식을 수정하는 것이 기반이 되었습니다. 또한, 커스텀 OPP 패키지와 Python 호스트 코드를 하나의 ABI(Application Binary Interface) 버전 단위로 취급한 것도 마찬가지였습니다. 오래된 커널은 오랫동안 모델 문제처럼 보일 수 있습니다. 모든 것을 사방에 로드하기보다 로딩 시점에 모델을 분할(Shard)하세요. Qwen 체크포인트는 약 169 GiB이며 1,610개의 safetensor 파일을 포함합니다. 이는 제가 사용한 브링업 구성 중 하나에서 사용 가능한 호스트 RAM보다 더 큰 크기였고, 개별 NPU의 메모리는 말할 것도 없었습니다. 저는 각 랭크(rank)가 소유한 전문가(expert)만 읽고, 필요한 곳에 밀집/공유 텐서(dense/shared tensors)를 유지하며, 전체 전문가 은행을 일시적으로 생성했다가 대부분 버리는 것을 방지하는 전문가 인식 로더(expert-aware loader)를 구축했습니다. 호스트 측의 전문가 데이터는 매핑되고 지연(lazily) 이동됩니다. 이로써 모델 로딩은 우발적인 메모리 스트레스 테스트에서 결정론적인 TP4/EP4 레이아웃으로 바뀌었습니다. 낮은 비트 가중치(low-bit weights)를 패킹된 상태로 유지하고 NPU에서 작업을 수행하세요. 제가 처음 사용해 본 W4 참조 디양자화된 패킹 가중치는 eager 경로에서 일반적인 matmul을 호출했습니다. 이는 정확도에 유용했지만, 기록된 스모크 케이스(smoke case) 하나에서는 0.229 tok/s만 관리할 수 있었습니다. 프로덕션 경로는 가중치를 패킹된 상태로 유지하고, 장치에서 전문가로 토큰을 라우팅하며, 그룹화된 전문가 투영(grouped expert projections)을 위해 커스텀 AscendC Cube 커널을 사용합니다. 저는 FRACTAL_NZ 레이아웃, 융합 게이트/업 처리(fused gate/up handling), 타일 감소(tiled reductions), 라우팅 및 타일 재사용(route and tile reuse), 그리고 W4 가중치를 더 큰 임시 표현으로 반복적으로 확장하는 대신 전용 W4A8 실행을 추가했습니다. 이는 속도 면과 용량 면 모두에서 이득입니다. 일시적인 확장된 전문가 은행을 피함으로써 상태, 캐시, 그래프 및 동시성(concurrency)을 위한 메모리를 확보할 수 있습니다. 제가 실제로 가진 모델에 대한 캐시를 구축하세요. Flash-Next는 일반적인 전체 어텐션 트랜스포머가 아닙니다. 제 구성에는 36개의 재귀 GDN 레이어와 12개의 희소 QSA 레이어가 있습니다. 이 모든 것을 일반적인 밀집 KV 캐시로 취급하는 것은 메모리를 낭비하고 상태 의미론(state semantics)을 놓치게 합니다.
저는 별도의 순환 상태 관리(recurrent-state management), 압축된 물리적 캐시 레이아웃, 접두사 상태 계층(prefix-state tiers), 희소 페이지 선택(sparse page selection), 직접 NZ 수집(direct NZ gathers), 그리고 310P 전용 QSA 경로를 구현했습니다. 이 서비스는 262,144 토큰 컨텍스트 제한으로 구성되어 있으며, 캐시 플래너는 약 4.08개의 그러한 창에 대한 용량을 유지합니다. 이는 메모리 계획 결과일 뿐이며, 모든 가능한 4-by-262K 워크로드가 종단 간(end-to-end) 포화 테스트를 완료했다는 주장으로 해석되어서는 안 됩니다. 토큰 루프에서 동기화 및 실행 오버헤드를 제거했습니다. 이 장치들에서는 임의의 디바이스-투-호스트 스칼라 읽기가 전체 파이프라인을 직렬화할 수 있습니다. 저는 hot-path .item() 호출을 제거하고, 단계별 텐서를 재사용했으며, 유용한 작업 뒤로 집합 연산(collectives)을 지연시키고, CPU 친화도를 강화했으며, 라우팅 및 희소 선택을 Python에서 분리했습니다. 즉시 경로(eager path)가 올바르게 작동한 후, 디코드 전용 ACL 그래프와 MTP2 추측 디코딩(speculative decoding)을 추가했습니다. 저는 보편적이라고 가정하기보다는 제가 제공하는 실제 동시성 형태를 포착합니다. 융합 연산자(Fused operators)와 그래프 재실행은 디코드 단계가 그렇지 않으면 많은 작은 커널 실행으로 구성되는 경우 엄청나게 중요합니다. 격리된 커널뿐만 아니라 서비스를 최적화해야 합니다. 여러 개의 커널이 마이크로벤치마크에서는 승리했지만 종단 간 테스트에서는 패배했습니다. 저는 실제 요청 시간을 단축한 것들만 유지하고 나머지는 거부하거나 격리했습니다. 다중 요청 QSA, 그룹화된 MTP 전문가(experts), 전문가 라우트 캐싱, 캐시 회계(cache accounting), 콜드-프리필 청킹(cold-prefill chunking), 그리고 집합 중첩(collective overlap)은 모두 API 경계에서 측정되었습니다. 마지막 부분이 바로 한 요청이 약 30 tok/s인 상황임에도 불구하고 네 개의 동시 요청이 약 61 aggregate tok/s에 도달하는 이유입니다. 추가 작업은 단일 토큰 스트림이 유휴 상태로 두는 기계의 일부를 점유할 수 있습니다.
Qwen의 성능은 오늘날 이룬 성과들입니다. 이는 통제된 단일 변수 벤치마크가 아니라 여러 단계와 워크로드에서 나온 마일스톤들입니다: Qwen3.8 Flash-Next 마일스톤 / 측정 결과 가장 초기, 비통제 서비스: 대략 0.2–1.9 tok/s, 종종 일관성이 부족함 Correct eager W4 디퀀트 레퍼런스: 0.229 tok/s 안정적인 W8 서비스 기준선: 약 18–19 tok/s 네이티브 W4A8, MTP2, 그래프, 단일 요청: 중앙값 29.74 tok/s; 최고치 34.34 tok/s 동일 최적화된 서비스, 네 개 요청: 총합 중앙값 60.88 tok/s 두 개의 동시 40K 워밍업 접두사 요청: 총합 30.76 tok/s 총합 40K 콜드 프롬프트: 약 120초 TTFT; 이후 30–32 tok/s 이 30/61 tok/s 수치는 짧고, 고정된 출력을 디코딩하는 테스트입니다. 긴 추론 요청이 더 좋지 않지만 더 유용한 이야기를 들려줍니다. https://reddit.com/link/1wvt1m4/video/rpc5c2c1s1th1/player 품질을 위해, 저는 4-chip Ascend W4 서비스와 비교를 위해 llama.cpp에서 다른 IQ4_XS GGUF로 실행된 RTX 6000 Pro 모두에 대해 198개의 GPQA Diamond 질문을 실행했습니다. 두 시스템 모두 동일한 AISBench 스타일의 답변 추출기를 사용하여 140/198 (70.71%)를 기록했습니다. 이는 Ascend 경로가 일관성이 있다는 증거입니다. 이는 순수한 하드웨어 또는 양자화 비교가 아니기 때문입니다. 실행 시간, 양자화, 채팅 템플릿 및 동시성(concur
AI 자동 생성 콘텐츠
본 콘텐츠는 Reddit AI Engineering의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기