M4 Max에서 Qwen3.8 Flash Next를 oMLX로 돌리면 128K에서도 초당 45토큰

M4 Max 128GiB에서 oMLX 0.7.0rc1과 MLX oQ4e 가중치로 32K씩 누적해 128K까지 쟀습니다. 생성은 128K에서도 45 tok/s, 새로 넣는 32K의 prefill은 770 tok/s 안팎으로 거의 떨어지지 않았습니다.

같은 M4 Max에서 Qwen3.8 Flash Next를 llama.cpp(GGUF) 대신 oMLX(MLX)로 돌려 봤습니다. 가중치는 MLX용 oQ4e 양자화(Jundot/Qwen3.8-Flash-Next-oQ4e-mtp)입니다. 결과는 llama.cpp 구성보다 크게 빨랐습니다. 128K까지 문맥을 쌓아도 생성은 초당 45토큰 안팎을 유지했고, prefill도 깊이에 따라 거의 느려지지 않았습니다.

GGUF와는 가중치 파일이 달라서, 같은 파일끼리 비교한 M4 Max와 Ryzen AI Max+ 395 비교 글에는 넣지 않고 따로 정리합니다.

44.89~45.24 tok/s128K 위치 생성 (MTP off, 3회)
770~775 tok/s128K 지점 추가 prefill
약 43초128K 지점 첫 토큰까지
0.7.0rc1oMLX 버전 (릴리스 후보)

측정 방식

공통 벤치마크 작업과 같은 틀입니다. 이탈리아어 소설과 C++ 코드 원문을 한 세션에서 32K토큰씩 이어 붙여 128K까지 채우고, 단계마다 새로 넣은 약 32K의 prefill 속도와 이어서 생성한 토큰의 속도를 쟀습니다. 소설과 코드 각각 3회입니다.

차이가 하나 있습니다. oMLX는 직전 단계에서 생성한 256토큰을 다음 prefill에서 다시 처리합니다. 토큰 ID와 누적 출력은 그대로 유지하지만 캐시 재사용 개수가 llama.cpp와 달라서, 이 결과는 같은 작업의 변형으로 기록했습니다. 가중치 파일 21개의 SHA256과 크기는 모두 확인했습니다.

결과: MTP off

누적 문맥 소설 prefill 소설 생성 코드 prefill 코드 생성
32K 786.70 49.42 800.98 50.57
64K 796.05 48.32 794.56 48.40
96K 786.56 46.75 779.55 47.00
128K 775.02 44.89 769.95 45.24

단위는 tok/s, 3회 평균입니다. 표준편차는 prefill이 3~8, 생성이 0.4~1.7 tok/s로 작았습니다. 첫 토큰까지는 모든 단계에서 41~43초였습니다.

같은 기계에서 llama.cpp로 같은 모델(GGUF UD-Q4_K_XL)을 쟀을 때는 128K 생성이 15.25~15.51 tok/s, 추가 prefill이 325~343 tok/s였습니다. 가중치가 달라서 이 차이를 런타임만의 효과로 볼 수는 없지만, 이 기계에서 실제로 쓸 수 있는 속도로는 oMLX 구성이 생성 약 3배, prefill 약 2.3배 빨랐습니다.

MTP3를 켜면

코드 입력에서 적응형 MTP(최대 3토큰 draft)를 켜 봤습니다.

누적 문맥 prefill 생성
32K 777.13 47.50
64K 771.98 45.31
96K 756.92 51.21
128K 746.66 58.40

128K에서 생성은 58.40 tok/s로 MTP off(45.24)보다 빨랐습니다. 그런데 한 요청 전체에 걸린 시간은 MTP off 48.62초, MTP3 48.69초로 같았습니다. 새로 넣는 32K의 prefill이 시간 대부분을 차지하고, 출력이 256토큰뿐이라 생성에서 아낀 시간이 묻혔습니다. 96K에서는 MTP3 생성 편차가 ±5.73 tok/s로 컸습니다. 출력이 길어지면 MTP의 이득이 커질 수 있지만 이 시험만으로 얼마나 커질지는 말할 수 없습니다.

8K 코드 선별에서는 MTP3가 약 76 tok/s까지 나왔는데, 긴 문맥에서는 그만큼 나오지 않았습니다. MTP는 출력 내용에 따라 수락률이 달라서 짧은 시험값을 긴 작업에 그대로 적용하면 안 됩니다.

그 밖에 확인한 것

  • 테이블 일부(PLE)를 RAM에 올려 두면 오히려 느렸습니다. 128K 생성이 약 27 tok/s로 SSD에 둘 때(약 45 tok/s)보다 낮았고, swap 증가로는 설명되지 않았습니다. 원인은 아직 모릅니다.
  • 4bit KV 압축(TurboQuant4)은 요청했지만 실제로는 적용되지 않았습니다. 이 모델의 attention 구조가 보존해야 하는 상태 때문에 압축이 꺼졌고, 4bit KV의 성능과 품질은 재지 못했습니다.
  • MTP off는 같은 입력에서 3회 출력이 정확히 같았고, MTP3는 64K부터 회차마다 출력이 달라졌습니다.

oMLX 0.7.0rc1은 정식 안정판이 아닌 릴리스 후보입니다. 출력 정확도나 긴 문맥 회상은 재지 않았습니다.