Mac Studio M5 Ultra에서 MiniMax H3, 768p 5초 영상 97초까지
M5 Ultra 256GB에서 MiniMax H3를 Mac용 엔진 VPIPE와 h3.c로 돌렸습니다. 1344×768·124프레임 텍스트→영상이 Turbo 4스텝과 int8 token 단계로 97초였고, 이미지·첫끝 프레임·참조 입력도 재 봤습니다.
MiniMax H3는 지금까지 Ryzen AI Max+ 395와 RTX Pro 6000 Blackwell에서 재 왔습니다. 이번에는 Mac Studio M5 Ultra(GPU 80코어, 통합 메모리 256GB, macOS 27.0.1)입니다. Mac에서 H3를 돌리는 엔진을 먼저 조사해 두 개를 골랐고, 두 엔진을 같은 작업으로 비교한 뒤 빠른 쪽의 가속 옵션을 하나씩 켜 가며 이 기계에서 가장 빠른 구성을 찾았습니다.
엔진 고르기
10월 26일에 Mac에서 H3를 돌릴 수 있는 엔진을 조사했습니다. 아래 수치는 모두 각 작성자가 보고한 값이고 우리가 잰 것이 아닙니다.
| 엔진 | 형태 | 판단 |
|---|---|---|
| h3.c | C + Metal CLI, MIT. 공식 bf16 가중치를 그대로 읽음 | 실측 |
| VPIPE | C++ 파이프라인 엔진 + 웹 UI·앱, Apache-2.0. int8 행렬곱, Sol-Attn, Sage, Turbo LoRA 런타임 적용 | 실측 |
| mlx-serve | Zig 서버 + Swift 앱, 자체 MLX 변환본 | 제외. 자체 문서에 1344×768·124프레임이 M4 Max에서 약 50분 |
| FastVideo FastH3 MLX INT6 | MLX | 제외. M4 Max 36GB에서 832×480·5초·8스텝 925초 |
| Python MLX 포트 여럿 | MLX | 제외. 8월 초 이후 정체, M5 Max에서 짧은 클립 약 45분이라는 보고 |
| ComfyUI (MPS) | Python | 제외. M5 Pro에서 480×864·약 9초·20스텝이 1시간 넘게 걸렸다는 보고 |
VPIPE 문서에는 두 엔진을 직접 비교한 값도 있습니다. 960×544·124프레임·6스텝, LoRA 없이 M5 Pro 24GB에서 VPIPE 5분 29초, h3.c 7분 11초였고, M4 Pro 64GB에서는 17분 43초와 23분 9초였습니다. M5 Pro의 h3.c는 메모리가 부족해 SSD 스트리밍과 bf16으로 돈 값입니다.
시험 환경과 작업
- 엔진: VPIPE main
11b8e4d, h3.c main8974cc0. VPIPE 웹 UI는 OpenSSL 4 환경에서 빌드되지 않아 CLI로만 썼습니다. - 가중치: Hugging Face 공식
MiniMaxAI/MiniMax-H3(rev42ed227ee) bf16과 LightX2V Turbo LoRA(rev30f485ed8). 파일마다 SHA256을 대조했습니다. 비교용으로 ComfyUI INT8 ConvRot DiT(Ryzen AI Max+ 395가 쓴 것과 같은 종류)도 받았습니다. - 재는 법: 실행부터 MP4 기록까지를 E2E로 쟀고, 최대 메모리는 프로세스의 peak footprint입니다. 모든 측정에서 swap 증가는 없었습니다.
- 같은 기계에서 상시 돌리는 LLM 서버가 GPU 메모리를 약 249GB 잡고 있어 H3와 동시에 돌릴 수 없습니다. 측정 동안 내렸다가 다시 올렸습니다.
| 작업 | 해상도 · 길이 | 스텝 · LoRA | 프롬프트 · 시드 |
|---|---|---|---|
| W1 | 960×544 · 124프레임 | 6스텝, LoRA 없음 | 피아노 치는 연주자 · 6 |
| W2 | 864×480 · 56프레임 | 8스텝 | 회전하는 종이 조형 · 17 |
| W3a | 1344×768 · 124프레임(5.17초) · 24fps | Turbo 4스텝, shift 영상 6 / 오디오 3 | 실험실을 걷는 작은 빨간 로봇(발소리 포함) · 20260831 |
| W3b | W3a와 같음 | 8스텝, LoRA 없음 | W3a와 같음 |
W3a의 프롬프트와 시드는 Ryzen AI Max+ 395 측정과 같습니다.
1차: 두 엔진 비교
먼저 같은 작업으로 두 엔진을 비교했습니다. 워밍업 1회 뒤 매번 새 프로세스로 3회 쟀고, 평균 ± 표본 표준편차입니다.
| 작업 | 엔진 | E2E (초) | denoise (초) | 영상 VAE (초) |
|---|---|---|---|---|
| W3b 8스텝 | h3.c | 350.3 ± 6.1 | 269.2 (스텝당 33.6) | 70.2 |
| W3b 8스텝 | VPIPE bf16 | 362.3 ± 3.5 | 324.3 (스텝당 40.5) | 27.0 |
| W1 6스텝 | h3.c | 102.7 ± 1.2 | 58.8 | 33.2 |
| W1 6스텝 | VPIPE bf16 | 107.0 ± 1.0 | 81.7 | 14.3 |
| W2 8스텝 | h3.c | 38.0 ± 0.0 | 16.9 | 11.1 |
LoRA 없이 8스텝을 돌리면 두 엔진의 전체 시간은 비슷했습니다. h3.c는 denoise가 17% 빠르고 영상 VAE가 2.6배 느려서 서로 상쇄됩니다.
W1은 위 VPIPE 문서의 비교와 같은 작업입니다. 다만 VPIPE는 int8 행렬곱(i8_gemm)을 켠 상태로 쟀습니다.
| W1 (초) | M5 Pro 24GB (작성자 보고) | M4 Pro 64GB (작성자 보고) | M5 Ultra |
|---|---|---|---|
| VPIPE | 329 | 1063 | 107 |
| h3.c | 431 | 1389 | 103 |
h3.c의 int8 행 단위 FC2 옵션(--use-int8-row-fc2)은 347초로 기본(350초)과 표준편차 안에서 같았고 출력만 바뀌었습니다. W2에 대해서는 h3.c PR #75 작성자가 M5 Ultra에서 49~57초를 보고했지만, 측정 하네스가 달라 직접 비교하지 않습니다.
h3.c는 LoRA를 읽지 못합니다. 그래서 4스텝 Turbo를 쓰는 W3a는 VPIPE로만 쟀습니다.
| VPIPE 구성 (W3a, Turbo v1.2) | E2E (초) | denoise (초) | 최대 메모리 |
|---|---|---|---|
| 공식 bf16, int8 행렬곱 끔 | 214.7 ± 4.0 | 174.0 | 49.7GB |
공식 bf16, int8 행렬곱(i8_gemm) |
199.3 ± 6.5 | 160.7 | 50.4GB |
공식 bf16, i8_gemm + Sol + Sage + PV8 |
110.3 ± 0.6 | 72.0 | 51.0GB |
| ComfyUI INT8 DiT, 기본 | 199.3 ± 1.5 | 160.7 | 30.9GB |
| ComfyUI INT8 DiT, Sol + Sage + PV8 * | 112.3 ± 0.6 | 73.7 | 31.4GB |
* 다른 파일 다운로드(약 13MB/s)와 시간이 겹친 측정입니다. 겹친 셀이 느려지지는 않았고, 같은 INT8 기본 구성을 다운로드와 겹쳐 쟀을 때가 187.3초로 오히려 빨랐습니다. VPIPE가 실행 중에 행렬곱 경로를 자동으로 고르면서 생기는 회차 간 변동으로 봅니다.
i8_gemm만으로는 7% 빨라졌고, Sol-Attn과 SageAttention, PV 8bit를 함께 켜자 199.3초가 110.3초가 됐습니다. Turbo LoRA v1.1과 v1.2는 속도가 같았습니다(197.0초와 199.3초, INT8 기본).
2차: 가속 옵션을 하나씩
1차에서 가장 빨랐던 bf16 + i8_gemm + Sol + Sage + PV8을 기준으로 옵션을 더 켜 봤습니다. W3a, 로봇 프롬프트이고, 따로 적지 않은 값은 워밍업 1회 뒤 1회만 잰 것이라 몇 초 차이는 의미를 두기 어렵습니다.
| 구성 | E2E (초) | denoise (초) | 메모 |
|---|---|---|---|
기준 (i8_gemm_tier 기본 accurate) |
109 | 67 | |
i8_gemm_tier: fast |
107 | 66 | 메모리 51→33GB |
i8_gemm_tier: token |
93 | 52 | 4회 평균 97.0 ± 1.0 |
| Sol τ 1.5 | 104 | 63 | 정확히 계산하는 키 블록 21.9%→13.2% |
token + τ 1.5 |
89.7 ± 0.6 (4회) | 48.7 | 구도는 기준과 같음 |
token + τ 2.0 |
85 | 45 | 로봇이 둘로 늘어나 쓰지 않음 |
| VAE를 ANE로 | 117 | 72 | 느려짐 |
| DiT 일부를 ANE로 | 117 | 75 | 느려짐. M5에서는 쓰지 말라는 문서와 같음 |
| VDN 선형 어텐션 (Sol 대신) | 163 | 121 | 5초 클립에서는 느림 |
| TaoMate-H3 3스텝 스트리밍 | 176 | 129 | 느리고 프롬프트에 없는 사람이 나옴 |
| Turbo FL2V v1.3 (v1.2 대신) | 116 | 74 | 구도가 다르고 속도 이득 없음 |
가장 큰 이득은 int8 행렬곱 단계를 token으로 올린 것이었습니다. 1회 측정끼리 109초에서 93초로 15% 줄었고, 가중치를 int8로 들고 있어 메모리도 51GB에서 33GB로 줄었습니다. VAE에 i8_gemm을 켜는 옵션은 H3의 VAE가 무시해서 출력이 그대로였습니다.
ComfyUI INT8 DiT를 쓰는 것은 이득이 없었습니다. int8 행렬곱 단계가 이미 INT8인 가중치에는 적용되지 않아서, 공식 bf16에 token 단계를 켠 쪽이 더 빨랐습니다.
Sol τ를 1.5로 올리면 T2V가 97초에서 89.7초로 더 빨라지지만 기본값으로 쓰지 않습니다. 이미지 참조 Ref2V에서 마지막 1초에 고양이가 둘로 늘었고, 정확 경로에서도 τ1.5면 같은 현상이 났습니다. τ1.0에서는 한 마리였습니다. τ2.0은 T2V에서도 로봇이 둘이 됐습니다.
입력 종류별 결과
같은 공통 설정(공식 bf16, i8_gemm + token 단계, Sol, Sage, PV8, Turbo 4스텝, 1344×768·124프레임)으로 입력 종류를 바꿔 쟀습니다. 표의 τ는 실제로 잰 값 그대로입니다. I2V와 FL2V, 영상 참조는 τ1.5로 쟀고 τ1.0으로는 재지 않았습니다. τ1.5를 기본값으로 쓰지 않는 이유는 위 콜아웃에 적었습니다.
| 작업 | 입력 | Sol τ | E2E (초) | denoise (초) | 최대 메모리 |
|---|---|---|---|---|---|
| T2V | 텍스트 | 1.0 | 97.0 ± 1.0 | 55.7 | 32.8GB |
| T2V | 텍스트 | 1.5 | 89.7 ± 0.6 | 48.7 | 32.8GB |
| I2V | 첫 프레임 | 1.5 | 93.7 ± 0.6 | 52.0 | 32.7GB |
| FL2V | 첫·끝 프레임 | 1.5 | 96.7 ± 0.6 | 55.0 | 32.9GB |
| Ref2V | 1024² 이미지 1장 | 1.0 | 102 (1회) | 57 | 92.4GB |
| Ref2V | 이미지 + 5.17초 영상(소리 포함) | 1.5 | 426.3 ± 5.9 | 350.7 | 102.9GB |
| Ref2VA 흉내 (FL2VA 가중치) | 1024² 이미지 | 1.5 | 128 (1회) | 77 | 94.9GB |
Ref2V는 공식 Ref2VA 파티션과 LightX2V Turbo Ref2V 4스텝 v1.0 768p LoRA를 썼고, 나머지는 Turbo FL2V v1.2입니다. 마지막 행은 Ref2V 가중치 없이 FL2VA 가중치로 참조 이미지를 넣어 본 것입니다.
어느 작업이든 고정 비용이 약 41초 있습니다. 텍스트 인코더 약 12초, 영상 VAE 약 26초, 오디오와 저장 약 3초입니다. Ref2V는 여기에 참조를 읽는 준비가 15초(이미지)에서 44초(영상) 더 듭니다.
영상 참조가 이미지 참조보다 훨씬 오래 걸리는 것은 시퀀스 길이 때문입니다. 960×544 참조 영상이 출력 크기인 1344×768로 올려져 3.8만 행이 더해지고, 전체 시퀀스가 8.4만 행이 됩니다. 참조 영상을 원래 크기로 두면(reference_video_short_edge: 0) INT8 기준 482초가 274초로 줄었지만, 고양이가 참조 영상 속 연주자의 옷을 입고 사람도 함께 나와 참조가 섞였습니다. 그래서 기본값(짧은 변 768)을 유지했습니다. 결과 영상은 참조 영상의 나무 톤 방과 고정 카메라를 따르고, 고양이 생김새는 참조 이미지를 따랐습니다.
참조 이미지는 짧은 변 1024로 넣었습니다. LightX2V Turbo가 학습할 때 쓴 정책(참조 면적을 출력 크기에 맞춤)과 이 이미지에서는 같은 크기입니다. VPIPE의 Ref2VA 기본값 2048은 행이 4배로 늘어납니다.
같은 시드면 같은 영상이 나오나
- h3.c는 모든 작업에서 4회 출력이 영상·오디오 모두 비트 단위로 같았습니다.
- VPIPE 기본(
accurate) 단계는 같은 시드라도 프로세스마다 출력이 달랐습니다. 행렬곱 경로와 어텐션 타일 크기를 실행 중에 시간을 재서 고르기 때문입니다. 같은 설정을 두 번 돌린 결과끼리 PSNR·SSIM은 4스텝 Turbo가 18.5~19.6dB·0.67~0.71, 8스텝이 27.4dB·0.93이었고, 구도는 같고 세부가 달랐습니다.VPIPE_H3_NO_QMM_AUTOTUNE=1 VPIPE_H3_ATTN_BQ=64를 주면 고정되는 것을 480p INT8 Turbo에서 3회 확인했고, 768p·bf16에서는 확인하지 않았습니다. token단계는 프로세스를 새로 띄워도 T2V·I2V·FL2V·이미지 Ref2V 출력이 비트 단위로 같았습니다. 다만 8.4만 행인 이미지 + 영상 Ref2V는 회차마다 달랐습니다.
화질
4스텝 T2V는 같은 설정을 다시 돌려도 PSNR이 약 19dB라서 PSNR로 경로 간 우열을 가리기 어렵습니다. 아래는 출력을 고정하는 환경 변수를 주고 768p Turbo v1.2를 1회씩 돌려, bf16·i8_gemm 끔을 기준으로 비교한 값입니다.
| 경로 | PSNR (dB) | SSIM |
|---|---|---|
bf16 + i8_gemm |
18.3 | 0.676 |
| ComfyUI INT8 | 17.3 | 0.625 |
| bf16 고속 (Sol + Sage + PV8) | 14.4 | 0.551 |
| INT8 고속 | 14.2 | 0.555 |
앞의 두 줄은 회차 간 차이 범위 안이라 우열을 가릴 수 없습니다. 고속 경로는 같은 시드에서 다른 표본을 만들었습니다. 배경이 모니터 벽 대신 유리 실린더가 되는데, 회차가 바뀌어도 그 구도를 유지하고 프레임 손상은 없어서 품질 저하가 아니라 다른 결과로 봅니다. 4스텝 T2V에서 token 단계와 기본 경로도 18.0dB·0.63으로 회차 간 차이 범위 안이었고, 눈으로 보면 구도가 같았습니다.
첫·끝 프레임이 고정되는 FL2V는 비교가 더 의미 있습니다. token + τ1.5와 accurate + τ1.0의 차이가 35.7dB·0.978로 작았습니다. 768p 출력은 모두 눈으로 봤을 때 정적 노이즈나 깨짐이 없었습니다.
다른 기계와 (참고)
같은 구성끼리 맞춘 비교입니다. 이 글의 대표값은 위의 M5 Ultra 최고 구성이고, 아래는 그와 다른 구성에서 잰 값입니다.
| 비교 | 그쪽 | M5 Ultra | 배율 |
|---|---|---|---|
| Ryzen AI Max+ 395, W3a, 같은 INT8 DiT·Turbo v1.1 | Dense 617초 | VPIPE INT8 v1.1 197.0초 | 3.1배 빠름 |
| Ryzen AI Max+ 395, W3a, Sol | 431초 (Turbo v1.1) | VPIPE INT8 Sol 119.3초 (Turbo v1.2) | 3.6배 빠름 |
| RTX Pro 6000 Blackwell, W3b 8스텝의 스텝당 | 7.0~7.8초 | h3.c 33.6초 / VPIPE 40.5초 | 4.3~4.8배 / 5.2~5.8배 느림 |
두 번째 줄은 LoRA 판이 달라서 첫 줄보다 거칠게 맞춘 비교입니다. Ryzen AI Max+ 395의 측정 과정은 HIP Sol 글에, Blackwell은 가속 경로 글에 있습니다.
하지 않은 것
- h3.c의 열린 PR(#75 지연 컴파일, #80·#73 VAE 정밀도, #14 Turbo LoRA를 가중치에 접기)은 재지 않았습니다. h3.c로 FL2V와 Ref2V도 재지 않았습니다.
- VPIPE의 텍스트 인코더 8bit 양자화, HyperFlow 8스텝, Ref2V 8스텝 LoRA의 화질, 10초 이상 긴 클립은 아직입니다. VDN 선형 어텐션은 길수록 유리하다고 문서에 적혀 있어 긴 클립에서는 다를 수 있습니다.
- GPU 클럭·온도·전력은 재지 않았습니다. 화질은 PSNR·SSIM과 눈으로 본 것뿐이고, 사람 평가나 지표 모델로 재지 않았습니다.
- 메모리는 VPIPE 값만 적었습니다. h3.c는 파일 매핑이 footprint에 잡히지 않는 것으로 보여 엔진 간 메모리 비교에 쓰지 않았습니다.