RAM 32GB 맥북과 워크스테이션에서 744B MoE 모델을 멈춤 없이 돌리는 세팅
TuBrief Editorial
August 24, 2026
0
컴퓨터/소프트웨어Written with AI assistance from the source video. The video is the authority.
More from the community
Comments (0)
Log in to leave a comment
No posts yet
Written with AI assistance from the source video. The video is the authority.
Log in to leave a comment
No posts yet
일반 워크스테이션이나 맥북에서 GLM-5.2 같은 744B MoE 모델을 로컬로 구동할 때, 병목은 VRAM 용량보다 스토리지 대역폭과 OS 가상 메모리 정책에서 먼저 터집니다. C 언어 기반 경량 인퍼런스 엔진인 JustVugg의 colibrì는 17B 크기의 상주 레이어(int4 기준 9.9 GiB)만 RAM에 고정하고, 21,504개로 쪼갠 라우팅 전문가 가중치(~370 GB)를 외장 SSD에서 토큰 단위로 실시간 스트리밍합니다.
문제는 기본 OS 설정 그대로 실행하면 스왑 트래싱이 발생하거나 커널 OOM Killer가 프로세스를 강제 종료한다는 점입니다. 컴파일 플래그부터 NVMe I/O 큐, 커널 파라미터까지 직접 손봐야 토큰 생성이 멈추지 않습니다.
colibrì의 코어 연산 엔진은 외부 의존성이 없는 약 1,300줄 분량의 단일 C11 파일입니다. 컴파일러가 어떤 SIMD 벡터 명령어를 쓰느냐에 따라 행렬 곱셈 연산 처리량이 갈립니다. 기본 -O2 빌드 대신 타깃 CPU의 정수 연산 확장 명령어를 직접 지정해야 합니다.
x86_64 리눅스 환경은 GCC 12 이상에서 AVX-512 VNNI를 켜고, Apple Silicon은 Clang을 통해 NEON DotProduct를 연결합니다.
Ubuntu 및 Debian 계열은 빌드 도구를 먼저 설치합니다.
sudo apt-get install gcc-12 libomp-dev
macOS 환경에서는 Homebrew로 OpenMP 런타임을 받습니다.
brew install libomp
x86_64 Linux 머신에서는 AVX-512 VNNI 명령어를 타깃으로 빌드합니다.
gcc -O3 -march=native -mtune=native \
-mavx512f -mavx512bw -mavx512vnni -mavx512dq \
-fopenmp -funroll-loops -ffast-math \
-o colibri_engine colibri_glm52.c -lm
Apple Silicon(M 시리즈) 환경에서는 라이브러리 경로를 직접 걸어 컴파일합니다.
clang -O3 -mcpu=native \
-march=armv8.4-a+dotprod+fp16 \
-Xpreprocessor -fopenmp \
-I/opt/homebrew/opt/libomp/include \
-L/opt/homebrew/opt/libomp/lib -lomp \
-o colibri_engine colibri_glm52.c -lm
구조체 관련 빌드 경고가 뜬다면 -std=c11 플래그를 붙여 해결합니다.
| 플랫폼 | 컴파일러 | 벡터 명령어 플래그 | 스레드 병렬화 |
|---|---|---|---|
| x86_64 (Linux) | GCC 12+ | -mavx512vnni -mavx512bw |
-fopenmp |
| ARM64 (macOS) | Apple Clang | -march=armv8.4-a+dotprod |
-Xpreprocessor -fopenmp |
| 구형 x86 | GCC / Clang | -mavx2 -mfma |
-fopenmp |
colibrì의 디코딩 지연 시간은 디스크의 1MB 단위 무작위 읽기 속도가 결정합니다. GLM-5.2의 라우팅 전문가 파라미터 파일은 개당 약 19 MB 크기로 나뉘어 있어, 토큰을 만들 때마다 비동기 I/O 스레드가 SSD에서 필요한 청크를 읽어옵니다.
패키지 매니저로 fio를 설치합니다.
# Linux
sudo apt-get install fio
# macOS
brew install fio
1MB 블록 크기와 직접 I/O(Direct I/O) 조건으로 무작위 읽기 대역폭을 측정합니다.
fio --name=colibri_stream_bench \
--filename=/Volumes/ExternalSSD/glm52_test.tmp \
--size=10G \
--rw=randread \
--bs=1m \
--iodepth=32 \
--numjobs=4 \
--ioengine=posixaio \
--direct=1 \
--group_reporting \
--runtime=60
Thunderbolt 4나 USB4(40 Gbps) 인터페이스는 실측 대역폭 2,8003,200 MB/s를 유지하며 0.080.10 tok/s 디코딩 속도를 냅니다. 반면 대역폭이 900~1,050 MB/s에 그치는 USB 3.2 Gen2(10 Gbps) 포트에 외장 드라이브를 물리면 100 토큰을 뽑는 데 80분 넘게 걸립니다.
+-------------------------------------------------------------------------+
| colibrì C Inference Engine |
| +--------------------------+ +-------------------------------------+ |
| | Dense Weights (9.9 GiB) | | Multi-Token Prediction (MTP) Head | |
| | Resident in RAM (mlock) | | int8 Quantized | |
| +------------+-------------+ +------------------+------------------+ |
+---------------+-----------------------------------+---------------------+
| |
v v
+-------------------------------------------------------------------------+
| Memory & Storage I/O Layer |
| +--------------------------+ +-------------------------------------+ |
| | Async Expert Readahead | | 21,504 Routed Experts (~370 GB) | |
| | I/O Queue Depth 32~64 | | Streamed from NVMe SSD via mmap | |
| +--------------------------+ +-------------------------------------+ |
+-------------------------------------------------------------------------+
비동기 프리패치(Async Expert Readahead)의 I/O 큐 깊이(iodepth)를 32~64 수준으로 늘리면 NVMe 컨트롤러의 병렬 채널을 전부 활용해 디스크 대기 지연을 줄일 수 있습니다.
32 GB RAM 시스템에서 9.9 GiB의 상주 가중치와 KV Cache, 파일 시스템 페이지 캐시가 동시에 올라가면 커널 메모리 경합이 일어납니다. 기본 리눅스 세팅에서는 370 GB 크기의 mmap 호출 시 가상 주소 공간 할당이 막히거나 OOM Killer가 엔진을 꺼버립니다.
/etc/sysctl.d/99-colibri-memory.conf 파일을 만들고 아래 내용을 입력합니다.
# 상주 메모리의 디스크 스왑 방출 억제
vm.swappiness = 1
# 가상 메모리 오버커밋 허용
vm.overcommit_memory = 1
# 비상 버퍼 메모리 공간 확보 (2GB)
vm.min_free_kbytes = 2097152
# 디스크 파일 캐시 보존율 상향
vm.vfs_cache_pressure = 50
# mmap 매핑 개수 제한 확장
vm.max_map_count = 524288
저장 후 파라미터를 즉시 반영합니다.
sudo sysctl --system
쉘 세션에서 메모리 잠금 한계를 풀어 상주 레이어의 mlock() 호출을 허용합니다.
ulimit -l unlimited
| 파라미터 | 기본값 | 권장값 | 설정 목적 |
|---|---|---|---|
| vm.swappiness | 60 | 1 | RAM에 고정한 9.9 GiB 가중치가 스왑 영역으로 밀려나는 현상 방지 |
| vm.overcommit_memory | 0 | 1 | 370 GB 분량 mmap 매핑 시 커널 메모리 거부 방지 |
| vm.vfs_cache_pressure | 100 | 50 | 파일 캐시 수명을 늘려 반복 호출되는 전문가 가중치 재사용 |
| vm.max_map_count | 65530 | 524288 | 21,504개 파라미터 파일 매핑 한도 해제 |
| ulimit -l | 64 (KB) | unlimited | Dense 레이어의 물리 메모리 고정(mlock) 권한 부여 |
macOS 환경에서는 여유 메모리가 고갈되면 dynamic_pager가 백그라운드에서 메모리 압축을 걸어 CPU 점유율을 갉아먹습니다. 구동 전 점유율이 높은 앱을 정리해 압축 엔진 진입을 막아야 합니다.
MoE 디코딩은 CPU 캐시와 메모리 버스를 쉴 새 없이 긁어옵니다. 다중 소켓 워크스테이션에서 NUMA 노드를 잘못 타면 인터커넥트 버스 병목으로 토큰 생성 속도가 반토막 납니다.
numactl --hardware로 외장 NVMe 컨트롤러와 직결된 물리 CPU 노드 번호를 먼저 확인합니다. 그다음 하이퍼스레딩 중복 할당을 피하고 물리 코어에만 스레드를 고정하는 쉘 스크립트를 작성합니다.
#!/usr/bin/env bash
set -euo pipefail
# 1. 커널 가상 메모리 설정
sudo sysctl -w vm.swappiness=1 > /dev/null
sudo sysctl -w vm.overcommit_memory=1 > /dev/null
sudo sysctl -w vm.max_map_count=524288 > /dev/null
sudo sysctl -w vm.vfs_cache_pressure=50 > /dev/null
sudo sync && echo 3 | sudo tee /proc/sys/vm/drop_caches > /dev/null
# 2. 메모리 잠금 한도 해제
ulimit -l unlimited
# 3. OpenMP 스레드 물리 코어 바인딩
export OMP_NUM_THREADS=16
export OMP_PROC_BIND=TRUE
export OMP_PLACES=cores
# 4. NUMA 노드 0 바인딩 실행
ENGINE_BIN="./colibri_engine"
MODEL_PATH="/mnt/nvme_ext/GLM-5.2-colibri-int4-g64-with-int8-mtp"
exec numactl --physcpubind=0-15 --membind=0 \
"${ENGINE_BIN}" \
--model "${MODEL_PATH}" \
--threads "${OMP_NUM_THREADS}"
Apple Silicon 맥북에서는 macOS의 QoS 데몬이 워커 스레드를 효율 코어(E-Core)로 넘기지 못하게 막아야 합니다. 우선순위를 강제로 높여 실행합니다.
sudo nice -n -20 taskpolicy -c default ./colibri_engine --model /Volumes/SSD/glm52_i4
이 네 가지 세팅을 끝내면 32 GB RAM 워크스테이션이나 맥북에서도 OOM 충돌 없이 744B MoE 모델을 로컬 디스크 스트리밍 방식으로 안정적으로 띄울 수 있습니다.