DGX Spark 2대, 1M 컨텍스트 도전기. (Qwen3.8-Flash-Next day-0)
주력 모델의 기준은 처음부터 고정돼 있었습니다. 1M 토큰, 그리고 어느 정도의 멀티유즈. 하드웨어는 DGX Spark 2대였고, GB10에 128GB 통합 메모리를 품은 기기를 200Gbps RoCE로 엮은 구성입니다. 사양서만 놓고 보면 "이건 되겠지" 싶은 조합이었죠.
결론부터 정리하면, 262K 서빙은 성공했고 300K needle도 통과했습니다. 완전한 1M는 아직 아닙니다. prefill을 약 365K 처리하는 지점에서 멈췄어요. 부분 성공인데, 한계는 명확하게 잡힌 상태입니다. 달리 말하면 "1M라는 문 앞까지는 갔는데, 문고리를 잡는 순간 멈춘" 그런 상황이었습니다.
day-0 스택
Flash-Next는 125B MoE라서 토큰당 실제로 움직이는 것은 6B랍니다. 옆에 51B 크기의 n-gram 임베딩 테이블이 붙어 있고요. 어텐션은 4레이어인데, 히스토리를 고정 크기 상태로 압축하는 GDN이 3개, Qwen Sparse Attention이 1개예요. Qwen4 아키텍처의 프리뷰이고, 멀티모달이며, 네이티브 컨텍스트는 262K입니다. 무엇보다 thinking 모델이에요. 기본적으로 생각하고, per-request로 껐다 켰다 할 수 있습니다.
첫 시도는 vLLM이었는데 n-gram 테이블에 걸렸습니다. PLE CPU offload가 2노드를 지원하지 않아서 에러가 바로 떴어요. 그래서 --ple-offload-embedding으로 멀티노드를 지원한다는 SGLang으로 갈아탔습니다. 그런데 문제는 day-0 이미지가 H200, B200, GB300용이라는 것이었어요. Spark의 GB10, SM121은 대상 밖이었고, 직접 패치해서 빌드할 수밖에 없었습니다.
패치는 두 종류였습니다. QSA 가드에 SM121을 붙이고, mrope 부분 한 곳을 고쳤죠. 그리고 여기서 제 발등을 찍었습니다. 가드 패치는 넣었는데 정작 is_sm120_supported의 import를 빼먹은 것이었어요. 이건 warmup에서만 드러나는데, 재시작 정책이 unless-stopped라서 크래시하면 6분 동안 모델을 다시 올리고 또 크래시하는 루프가 만들어졌습니다. 돌고 도는 회전문에 갇힌 기분이었죠.
처음엔 "패치가 잘못됐나" 하고 한참을 헤맸습니다. 결국 크래시 로그를 다시 보다가 import 한 줄이 빠진 것을 발견했어요. 한 줄을 넣으니 부팅이 성공했습니다. 2노드 TP2, NCCL over RoCE, PLE offload, MTP 추측 디코딩을 켰고, 모델 로딩에 5.8분이 걸립니다. 삽질의 대부분이 환경과 씨름하는 데서 나온다는 걸 또 한 번 느꼈습니다.
thinking 예산의 함정
첫 벤치는 무효였습니다. 한쪽은 thinking OFF, 다른 쪽은 ON, 조건 자체가 달랐거든요. 그리고 더 깊은 함정이 하나 있었어요. thinking 모델에 max_tokens 300을 주면, thinking이 그 예산을 전부 써버립니다. 결과는 finish=length, content 0. 처음 벤치에서 content가 안 나온 것도 바로 이 원인이었습니다. 모델의 문제가 아니었던 것이죠. 마치 회의 시간 30분짜리를 잡았는데, 등장인물의 머릿속 독백이 29분 동안 이어져서 결론을 말할 시간이 없어진 것과 비슷합니다.
코딩 질문이면 thinking만이 800~1,700+ 토큰을 쓰고, 자유문은 37토큰이었습니다. 프롬프트에 따라 엄청나게 변동합니다. 둘 다 thinking ON, 예산 4096 통일로 재설계하고 다시 쟀습니다.
262K, 나온 수치
262K 서빙은 KV 풀 668,672 토큰으로 올라왔습니다. thinking ON이면 간단한 질문에 TTFT 0.23~0.35초, 생각 43토큰 뒤에 답이 옵니다. thinking OFF 디코드는 30~45 tok/s. 동시 4요청을 쏘면 60 tok/s 집합이고, thinking ON이면 28.1 tok/s입니다. 짧은 요청을 많이 보내는 에이전트에게는 0.23초라는 첫 토큰 대기시간이 사실상 전부입니다. 대기하는 0.23초 동안 커피 한 모금도 못 마실 정도로, 체감상 "즉답"에 가까웠어요.
커뮤니티에서 걱정하는 할루 시험도 해봤습니다. 존재하지 않는 행성 NGC-7742b와 존재하지 않는 교수의 경력을 물어봤는데, 둘 다 전제가 거짓인 질문이었고 둘 다 전제 자체를 거부했습니다. "NGC 번호는 행성에 부여되지 않는다", "재직하지 않는다". 2건에 불과해서 보증은 아니지만, 적어도 경보는 실측으로 확인되지 않았습니다.
1M 레시피
1M 확장 레시피는 Qwen의 Hugging Face 모델카드에 적혀 있습니다. 여기서 config.json을 직접 고치는 것은 막다른 길이에요. draft 모델 config가 엮여 들어와서 부팅에서 AttributeError로 크래시합니다. 공식 경로는 --json-model-override-args 인자에 YaRN factor 4.0을 주는 것입니다.
SGLANG_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN=1 sglang serve \
--json-model-override-args '{"text_config": {"rope_parameters": {
"mrope_interleaved": true, "mrope_section": [11, 11, 10],
"rope_type": "yarn", "rope_theta": 10000000,
"partial_rotary_factor": 0.25, "factor": 4.0,
"original_max_position_embeddings": 262144}}}' \
--context-length 1000000
SGLANG_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN=1 환경변수가 없으면 262K에 그대로 남습니다. KV 공간을 확보하려고 mamba 캐시 슬롯을 97에서 24로 줄였더니 KV 풀이 1,632,448 토큰이 됐습니다. 1M 요청 하나를 넣어도 여유가 있는 크기였어요.
300K 통과, 977K 멈춤
needle 테스트에서 처음 넘어지는 것은 토크나이저였습니다. chars/token으로 추정한 1M 문서가 30% 빗나가서 1.31M 요청이 됐고, 엔진 크래시 2회. 실제 토크나이저로 실측하니 문단 하나당 74~75토큰이었습니다.
그다음은 됐습니다. 300,382 토큰 문서, 네이티브 262K를 38K 토큰을 넘긴 크기였는데, 40% 지점에 숨긴 코드가 돌아왔어요. wall 179초. YaRN 확장이 실존한다는 증거이자, 262K를 실제로 넘어선 첫 신호였습니다.
그리고 976,837 토큰 문서, 1M 경계 바로 아래로 정확히 생성한 그것에서 멈췄습니다. prefill 중 약 364K 처리 지점에서 hang이었어요. 다시 쏘니 정확히 같은 지점, pending 612,345. 결정론적이었습니다. 랜덤이 아니라, 항상 같은 자리에서 걸리는 것이었죠. watchdog 300초, CUDA coredump, 자동 재기동 4회. 여기서 한계를 인정하고 관뒀습니다.

닿은 곳은 여기까지입니다. 262K와 멀티유즈는 Flash-Next가 실사용 가능한 수준이었어요. TTFT 0.23초, 동시 4요청 60 tok/s, 할루 시험도 이상 없음. 완전한 1M은 레시피 확보에 365K까지 검증했고, 그 이상은 day-0 빌드의 한계였습니다. 참고로 27B 모델은 단 1개 Spark에서 1M이 정상 동작하니, 하드웨어의 탓은 아니라는 것도 확인된 사실입니다.
배분은 명확해졌습니다. 1M 실전 작업은 지금 쓰는 모델이 그대로 가고, 1M 미만의 인터랙티브와 에이전트는 Flash-Next가 후보입니다. SGLang이 Qwen4Exp의 1M을 안정화하는 업데이트가 나오면 다시 도전합니다. 그때까지는, 뭐 별 수 있겠어요. 기다리는 수밖에.
'공부 > 인공지능' 카테고리의 다른 글
| H3를 직접 돌려봤다. Wan 2.2와 스프라이트 7모션 비교 (레고 로봇) (0) | 2026.08.29 |
|---|---|
| 게임 스프라이트를 로컬 Wan 2.2로 뽑아봤다. (핑크팬더 5모션) (0) | 2026.08.28 |
| [세컨드브레인 개발기] 16. 122B와 27B — 커도, 빠른 것도 다 이긴 건 아니었다 (0) | 2026.08.26 |
| [세컨드브레인 개발기] 15. 주력 모델이 3번 바뀌었다. 사유도 각각 달랐다. (0) | 2026.08.18 |
| [세컨드브레인 개발기] 14. GB10 에서 배운 것 — 속도는 대역폭을 활성 파라미터로 나눈 값이다 (0) | 2026.08.16 |