M5 Ultra 256GB에서 DeepSeek V4.1 Flash 1017, 128K 위치 생성 초당 37토큰

Mac Studio M5 Ultra 256GB에서 DeepSeek V4.1 Flash 1017 Q2의 일반 가중치를 모두 메모리에 올리고 128K까지 누적해 쟀습니다. 128K 생성 37 tok/s, M4 Max보다 생성 약 2.1~2.3배, prefill 4~6배였습니다.

Mac Studio M5 Ultra(GPU 80코어, 통합 메모리 256GB)에서 M4 Max 글과 같은 DeepSeek V4.1 Flash 1017 Q2 파일을 같은 작업으로 쟀습니다. 파일의 SHA256까지 같습니다. M4 Max는 128GiB에 맞추려고 SSD 스트리밍과 분리 배치를 썼지만, 256GB에서는 매 레이어 읽는 일반 가중치를 모두 메모리에 올릴 수 있어서 SSD 스트리밍 없이 돌렸습니다. Engram 표는 여기서도 디스크에서 읽습니다.

소설과 코드 각각 8K 단독 3회, 32K씩 128K까지 누적 3회, 모두 30단계가 실패나 제외 없이 끝났습니다.

37.03~37.06 tok/s128K 위치 생성 (3회 평균)
1455~1591 tok/s128K 지점 추가 prefill
약 21~23초128K 지점 첫 토큰까지
30/30실패·제외·재측정 없이 유효한 단계

이 결과를 읽을 때 알아 둘 것

  • M4 Max 글과 같이 HTTP 서버가 아니라 엔진의 C 세션 API를 직접 불러 쟀습니다. ds4 서버에는 토큰 ID를 그대로 받는 경로가 없어서 공통 벤치마크 원형(HTTP 스트리밍)으로는 잴 수 없습니다. 이 기계용 측정 프로그램은 M4 Max 것을 가져오지 못해 같은 정의로 새로 짰습니다.
  • 엔진은 ds4 main ee7e840에 아직 병합되지 않은 PR 두 개(#1261, #1262)를 얹은 빌드입니다. main 그대로도 같은 조건으로 재서 함께 적었습니다.
  • 생성 속도 계산식이 M4 Max 쪽과 조금 다릅니다. 이 글의 표는 256 ÷ (prefill 끝 → 256번째 토큰), M4 Max는 255 ÷ (첫 토큰 → 256번째 토큰)이고, 이 글 방식이 0.4% 정도 높게 나옵니다. 두 기계를 비교할 때는 계산식을 맞춘 128K 값만 씁니다.

사용 설정

항목 값
기계 Mac Studio, M5 Ultra (GPU 80코어), 256GB, macOS 27.0.1
모델 antirez DeepSeek V4.1 Flash 1017 Q2 (IQ2_XXS/Q2_K), M4 Max 글과 같은 파일
배치 일반 가중치 전부 메모리 상주(모델 151.76 + 버퍼 8.18 + KV 0.82 = 160.75GiB 계획), Engram은 디스크에서 읽음, SSD 스트리밍 없음
엔진 ds4 main ee7e840 + PR #1261 + PR #1262 (로컬 병합)
backend Metal, Metal 4 tensor API 켜짐
prefill 단위 / context 8,192 / 135,168
MTP off
생성 greedy, 256토큰, EOS 제외
반복 매번 새 프로세스, 짧은 인사로 워밍업한 뒤 상태를 비우고 측정

결과

64K부터는 앞 단계의 KV를 재사용하고 새 32,769토큰만 처리합니다. 8K 행은 누적과 별개로 새 프로세스에서 8K를 한 번에 넣은 값입니다.

소설

문맥 prefill (tok/s) 첫 토큰 (초) 생성 (tok/s)
8K (단독) 1341.69 6.11 39.23
32K 1560.02 21.00 38.19
64K 1525.34 21.48 37.85
96K 1489.76 22.00 37.42
128K 1455.11 22.52 37.03

코드

문맥 prefill (tok/s) 첫 토큰 (초) 생성 (tok/s)
8K (단독) 1436.64 5.70 39.30
32K 1777.88 18.43 38.25
64K 1670.98 19.61 37.90
96K 1607.96 20.38 37.48
128K 1590.56 20.60 37.06

3회 평균이고 변동계수는 생성 0.37%, prefill 0.10% 이하였습니다. 같은 원문과 문맥에서는 세 회차의 출력 토큰이 모두 같았습니다. 측정 내내 swap은 0이었고, 짧게 튄 백그라운드 작업 말고는 다른 부하가 없었습니다.

생성은 8K에서 128K까지 6% 정도만 줄었습니다. 128K 지점에서 32K를 더 넣고 첫 토큰을 받기까지 21~23초입니다.

PR 두 개가 생성을 43~52% 올렸습니다

같은 조건에서 main 그대로와 PR을 얹은 빌드를 비교했습니다.

문맥 소설 생성 main → PR 코드 생성 main → PR
8K 27.36 → 39.23 (+43.4%) 27.30 → 39.30 (+44.0%)
32K 26.43 → 38.19 (+44.5%) 26.41 → 38.25 (+44.8%)
64K 25.71 → 37.85 (+47.2%) 25.89 → 37.90 (+46.4%)
96K 25.23 → 37.42 (+48.3%) 25.43 → 37.48 (+47.4%)
128K 24.35 → 37.03 (+52.1%) 24.55 → 37.06 (+51.0%)

prefill은 두 빌드가 0.2% 안에서 같았고, 30단계의 출력 토큰도 두 빌드가 완전히 같았습니다. 두 PR이 디코딩만 바꾸기 때문입니다.

PR 내용과 소스를 읽어 보면 이유가 짐작됩니다. main은 레이어마다 command buffer가 끝나기를 기다렸습니다. 토큰당 약 9.8GiB를 읽으면서 초당 27토큰이면 실효 대역폭은 약 290GB/s로, 메모리 대역폭이 아니라 이 고정 대기에 막혀 있었던 셈입니다. PR #1261은 이 대기를 파이프라인으로 바꿉니다. PR #1262는 긴 문맥 디코딩에서 indexer 후보 계산을 줄여서, 문맥이 길수록 이득이 커지는 모양(8K +43%, 128K +52%)과 맞습니다.

M4 Max와 나란히

같은 모델 파일, 같은 작업, 같은 측정 방식(C 세션 API)으로 잰 두 기계의 대표 결과입니다. 다만 두 기계의 설정이 다르고, 그 차이가 배율에 들어 있습니다.

M5 Ultra M4 Max
GPU / 메모리 80코어 / 256GB 40코어 / 128GiB
배치 일반 가중치 전부 상주 SSD 스트리밍 + 자동 expert 캐시, Engram은 외장 SSD
엔진 main + PR #1261, #1262 PR #1073, #1225, #1263 후보 + 분리 배치
Metal 4 tensor API 켜짐 해당 없음
문맥 소설 prefill M5 Ultra / M4 Max 배율 코드 prefill M5 Ultra / M4 Max 배율
8K (단독) 1341.69 / 220.09 6.10 1436.64 / 217.76 6.60
32K 1560.02 / 381.02 4.09 1777.88 / 381.41 4.66
64K 1525.34 / 350.41 4.35 1670.98 / 315.94 5.29
96K 1489.76 / 313.07 4.76 1607.96 / 303.44 5.30
128K 1455.11 / 293.68 4.95 1590.56 / 290.27 5.48

생성은 계산식을 맞춘 128K 값으로 비교하면 소설 36.89 대 17.75 tok/s(2.08배), 코드 36.91 대 16.11 tok/s(2.29배)입니다. prefill은 누적 단계에서 4.1~5.5배, 8K 단독에서 6.1~6.6배였고, 128K 지점의 첫 토큰은 약 112초에서 21~23초로 줄었습니다.

이 배율은 칩 차이만이 아닙니다. M5 Ultra는 메모리가 넉넉해 가중치를 상주시켰고, M4 Max는 SSD 스트리밍을 썼습니다. 두 쪽 모두 병합되지 않은 PR을 넣었지만 넣은 PR이 다릅니다. 두 기계의 출력 토큰을 서로 대조하지도 않았습니다. 엔진이 달라서 같은 출력이 나온다고 가정하지 않습니다.

prefill의 큰 몫은 아직 M5의 행렬 가속을 쓰지 않습니다

ds4 ee7e840 소스를 보면, prefill 행렬곱의 큰 몫인 라우팅 전문가 커널(IQ2_XXS, Q2_K)은 Metal 4 tensor 경로가 아니라 예전 simdgroup 행렬곱으로 돕니다. tensor 경로는 Q8_0 dense 투영과 attention의 저랭크 투영 등에만 쓰입니다. Qwen용 전문가 커널에는 tensor 경로가 있지만 DeepSeek V4.1의 이 양자화 형식에는 아직 없고, 10월 26일 기준으로 이를 다루는 업스트림 PR도 찾지 못했습니다. prefill이 앞으로 더 빨라질 여지가 남아 있다는 뜻입니다.

같은 기계에서 MXFP4를 쓰면

같은 가중치의 MXFP4 판(467.2GiB)은 256GB에도 들어가지 않아서 SSD 스트리밍으로 돌려야 합니다. 같은 작업을 같은 두 빌드로 재 봤고, 24회 모두 유효했습니다. 모델 파일이 달라 대표 결과는 아니고, "이 기계에서 MXFP4를 쓰면 얼마나 느려지나"로 읽어야 합니다. 출력 품질은 비교하지 않았습니다.

128K 지점 MXFP4 (SSD 스트리밍) Q2 (상주)
소설 생성 15.17 tok/s 37.03 tok/s
코드 생성 13.45 tok/s 37.06 tok/s
소설 prefill 446.67 tok/s 1455.11 tok/s
코드 prefill 422.95 tok/s 1590.56 tok/s

전체 단계로 보면 생성은 Q2 상주의 0.32~0.43배, prefill은 0.20~0.46배였습니다. 몇 가지를 더 확인했습니다.

  • Q2 상주에서 생성을 43~52% 올린 두 PR이 여기서는 ±3% 안이었습니다. SSD 스트리밍에서는 토큰 간격이 55~77ms로 길어서, PR이 없앤 고정 대기가 병목이 아닙니다.
  • ds4가 자동으로 정하는 전문가 캐시(이 기계에서 동적 162GiB)를 쓰면 생성이 0.3~0.46 tok/s까지 떨어지는 경우가 있었습니다. 엔진 소스 주석에는 권장 작업 메모리에 너무 가까우면 짧은 prefill이 VM·드라이버 동기화에 시간을 다 쓴다고 적혀 있고, 저장소 문서에 자동 캐시를 256GB 기계에서 검증한 기록은 없었습니다. 그래서 캐시를 96GB로 정했고, 96GB에서는 한 번도 그렇게 느려지지 않았습니다.
  • 프로세스마다 첫 디코딩의 처음 1~4토큰이 토큰당 0.3~2.2초씩 멈췄습니다. 32K 단계 생성 속도의 편차는 거의 이것 때문이고, 자동 캐시에서 본 느린 상태와 같은 원인일 수도 있지만 가설일 뿐 확인하지 않았습니다.

범위

출력 품질, MTP 같은 speculative 가속은 재지 않았습니다. HTTP 서버를 거치는 공통 벤치마크 원형은 ds4 서버에 토큰 ID 경로가 생기면 다시 잴 예정입니다. Ryzen AI Max+ 395(EVO-X2)에서 같은 방식으로 잰 DeepSeek 결과는 아직 없습니다.