Skip to content
Published on

Apple Silicon에서 LLM 서빙하기: M4/M5 칩의 비밀과 한계

Authors

Apple Silicon이 AI 추론 시장을 흔드는 이유

2024년 말, 한 스타트업 ML 엔지니어로부터 이런 말을 들었습니다. "RTX 4090 있는 워크스테이션 두고 왜 맥북으로 LLM 돌려요?" 그 엔지니어가 M4 Max 맥북에서 Llama 3.1 70B 모델이 8 tokens/sec로 돌아가는 걸 보고 나서 표정이 바뀌었습니다. RTX 4090 단일 카드는 VRAM이 24GB라 70B 모델 자체를 올릴 수 없거든요.

Apple Silicon의 LLM 추론 성능은 단순한 벤치마크 숫자 이상의 의미를 갖습니다. 아키텍처 수준에서 근본적으로 다른 접근을 취하고 있기 때문입니다. 이 글에서는 M4/M5 칩의 내부 구조를 분해하고, 실제로 LLM을 돌릴 때 무슨 일이 일어나는지 상세히 설명합니다.


1. 핵심 차별점: 유니파이드 메모리 아키텍처 (UMA)

Apple Silicon의 가장 중요한 특징은 **유니파이드 메모리 아키텍처(Unified Memory Architecture, UMA)**입니다. 이것이 왜 중요한지 이해하려면 먼저 전통적인 PC 아키텍처와 비교해야 합니다.

전통적인 PC 아키텍처의 병목

전통적인 시스템에서 CPU와 GPU는 물리적으로 분리된 메모리를 사용합니다.

전통적인 PC 아키텍처:
┌─────────────────────┐   PCIe x16 (~32 GB/s)   ┌──────────────────────────┐
CPU                 │◄──────────────────────►  │ GPUIntel/AMD           │                           │ NVIDIA RTX 4090DDR5 64GB           │                           │ GDDR6X 24GB              │
89 GB/s bandwidth   │                           │ 1008 GB/s bandwidth      │
│                     │                           │                          │
│ 추론 중인 모델 조각  │   데이터 복사 필요!        │ 추론 중인 모델 조각        │
└─────────────────────┘                           └──────────────────────────┘

문제점:
- LLM 추론 시 weight는 GPU VRAM, KV cache는 부분적으로 CPU RAM에 → 복사 오버헤드
- PCIe 대역폭 32 GB/s는 GPUVRAM 1TB/s 대비 30배 이상 느림
- 70B 파라미터 모델 (FP16) = ~140GB → 24GB VRAM에 아예 올라가지 않음!

Apple M4 Max의 접근법

Apple M4 Max (유니파이드 메모리):
┌─────────────────────────────────────────────────────────────────┐
│                    128GB Unified Memory Pool546 GB/s bandwidth                         │
│                                                                 │
│   ┌────────────┐   ┌──────────────┐   ┌──────────────────────┐ │
│   │   CPU      │   │     GPU      │   │   Neural Engine      │ │
│   │ 14 cores   │   │  40 GPU cores│   │   38 TOPS            │ │
 (4P + 10E) │   │              │   │   INT8/FP16 전용     │ │
│   └────────────┘   └──────────────┘   └──────────────────────┘ │
│                                                                 │
│   모든 프로세서가 동일한 물리적 메모리에 직접 접근!│   복사 없음, 지연 없음, 동기화 오버헤드 없음                    │
└─────────────────────────────────────────────────────────────────┘

왜 LLM 추론에서 이게 게임 체인저인가?

LLM 추론의 핵심 병목은 compute bound가 아닌 memory bandwidth bound입니다. 이를 이해하기 위해 Roofline 모델을 살펴봅시다.

Arithmetic Intensity (산술 강도) = FLOPs / Memory Bytes

Transformer의 attention 메커니즘과 linear layer에서:

  • 행렬-벡터 곱 (batch size 1일 때): weight 1번 읽고 곱셈 1번 → Arithmetic Intensity ≈ 1
  • 행렬-행렬 곱 (batch size 크면): Arithmetic Intensity 높아짐

M4 Max의 peak FP16 성능은 ~14.2 TFLOPS이고, 메모리 대역폭은 546 GB/s입니다. Roofline 전환점: 14.2 TFLOPS / 0.546 TB/s = ~26 FLOP/byte

단일 쿼리(batch=1) 추론 시 Arithmetic Intensity가 ~1 FLOP/byte이므로, 완전히 메모리 대역폭 제한입니다. 즉, 최고 throughput은 이론상 546 GB/s를 활용하는 수준이 상한선입니다.

이 관점에서 M4 Max의 546 GB/s는 RTX 4090의 1008 GB/s보다는 낮지만, 모델 자체가 메모리에 올라갈 수 있다면 사용 가능한 메모리 공간이 훨씬 유리합니다.

모델 크기별 FP16 메모리 요구량:
Llama 3.2 3B   → ~6GB   (M4 Pro 24GB에 쉽게 올라감)
Llama 3.1 8B   → ~16GB  (M4 Pro 24GB에 올라감)
Llama 3.1 70B  → ~140GB (M4 Max 128GB에 Q4 양자화 필요, ~40GB)
Llama 3.1 405B → ~810GB (M4 Ultra 192GB에도 불가, 양자화 필수)

2. Apple Neural Engine (ANE) 해부

많은 사람들이 "Apple Silicon의 AI 성능 = Neural Engine" 이라고 착각합니다. 실제는 훨씬 미묘합니다.

ANE는 GPU가 아니다

Neural Engine(ANE)은 Apple이 A11 Bionic(2017)부터 탑재한 전용 AI 가속기입니다. GPU와는 완전히 다른 목적으로 설계되었습니다.

Apple M4 프로세서 내 컴포넌트 역할:
┌────────────────────────────────────────────────────────────────┐
Apple M4 Max│                                                                │
CPU (4P + 10E cores)- 범용 연산, OS, 애플리케이션 로직                              │
- Prefill phase에서 tokenization 담당                          │
│                                                                │
GPU (40 cores)- Metal API로 프로그래밍 가능                                   │
- LLM의 행렬 곱, attention 연산 처리                           │
- llama.cpp, MLX가 주로 사용                                   │
│                                                                │
Neural Engine (38 TOPS)- CoreML 모델 전용 가속                                         │
- INT8/FP16 systolic array MAC 유닛                            │
- 직접 프로그래밍 불가! (CUDA 같은 범용 API 없음)- Whisper, Face ID, Siri 처리에 사용                           │
│                                                                │
└────────────────────────────────────────────────────────────────┘

ANE의 내부 구조

ANE는 systolic array 기반의 MAC(Multiply-Accumulate) 유닛 배열로 구성됩니다. M4의 ANE는 38 TOPS(INT8)를 처리할 수 있는데, 이는 행렬 곱을 파이프라인 방식으로 처리하는 구조입니다.

Systolic Array (간략화):
입력 행렬 →  [MAC][MAC][MAC][MAC]  → 출력
              ↓    ↓    ↓    ↓
입력 행렬 →  [MAC][MAC][MAC][MAC]
              ↓    ↓    ↓    ↓
입력 행렬 →  [MAC][MAC][MAC][MAC]

MAC 유닛: multiply + accumulate를 동시 실행
데이터가 좌→우로 흐르고, weight가 위→아래로 흐르는 패턴

CoreML과 ANE 활용

ANE를 활용하려면 CoreML 프레임워크를 통해야 합니다:

# CoreML로 LLM 변환 (개념적 예시)
import coremltools as ct
import torch

# PyTorch 모델 → CoreML 변환
model = load_llm_model()
traced_model = torch.jit.trace(model, example_input)

# CoreML 변환 시 compute_units 지정
mlmodel = ct.convert(
    traced_model,
    compute_units=ct.ComputeUnit.ALL,  # CPU + GPU + ANE 모두 사용
    # 또는 ct.ComputeUnit.CPU_AND_NE  # CPU + ANE만
    minimum_deployment_target=ct.target.macOS14,
)
mlmodel.save("llm_model.mlpackage")

현실적인 한계: 대부분의 LLM 서빙 프레임워크(llama.cpp, vLLM, Ollama)는 ANE를 직접 활용하지 않습니다. ANE는 CoreML 전용이고, CoreML 변환은 모든 LLM 아키텍처를 지원하지 않습니다. 실질적인 LLM 추론의 대부분은 GPU 경로를 사용합니다.


3. Metal Performance Shaders와 MLX

Metal: Apple GPU의 프로그래밍 레이어

NVIDIA가 CUDA를 제공하듯, Apple은 Metal을 제공합니다. PyTorch의 MPS(Metal Performance Shaders) 백엔드는 Metal을 통해 Apple GPU를 활용합니다.

# PyTorch MPS 백엔드 사용
import torch

# MPS 사용 가능 여부 확인
print(torch.backends.mps.is_available())   # True on Apple Silicon
print(torch.backends.mps.is_built())       # True if compiled with MPS

device = torch.device("mps")

# 모델을 MPS로 이동
model = YourTransformerModel()
model = model.to(device)

# 텐서 연산도 MPS에서 실행
x = torch.randn(1, 512, device=device)
output = model(x)

# 내부적으로 일어나는 일:
# PyTorch → MPS 백엔드 → Metal API → GPU 커널 실행
# CUDA와 달리 커널 코드를 MSL(Metal Shading Language)로 작성

MLX: Apple Silicon을 위한 머신러닝 프레임워크

2023년 말 Apple이 공개한 MLX는 Apple Silicon을 위해 처음부터 설계된 ML 프레임워크입니다. NumPy와 유사한 API를 제공하면서도 Apple Silicon의 유니파이드 메모리를 최대한 활용합니다.

import mlx.core as mx
import mlx.nn as nn

# MLX의 핵심: 지연 평가 (Lazy Evaluation)
a = mx.array([[1.0, 2.0], [3.0, 4.0]])
b = mx.array([[1.0, 0.0], [0.0, 1.0]])

# 이 시점에서는 아직 계산이 일어나지 않음!
c = a @ b        # 계산 그래프만 구성
d = mx.exp(c)    # 추가 연산 그래프 추가
e = d.sum()      # 또 추가

# mx.eval() 호출 시 전체 그래프를 한 번에 최적화하여 실행
mx.eval(e)       # 이 때 실제 GPU 연산이 일어남

print(e)  # [[2.71828...]]

지연 평가의 이점:

  1. 연산 그래프 최적화: 불필요한 중간 메모리 할당 제거
  2. 커널 fusion: 여러 작은 연산을 하나의 GPU 커널로 합침
  3. 유니파이드 메모리 활용: CPU/GPU 간 명시적 데이터 이동 없음
# MLX로 간단한 Transformer attention 구현
import mlx.core as mx
import mlx.nn as nn
import math

class MultiHeadAttention(nn.Module):
    def __init__(self, d_model: int, num_heads: int):
        super().__init__()
        self.num_heads = num_heads
        self.d_head = d_model // num_heads
        self.scale = math.sqrt(self.d_head)

        self.q_proj = nn.Linear(d_model, d_model)
        self.k_proj = nn.Linear(d_model, d_model)
        self.v_proj = nn.Linear(d_model, d_model)
        self.out_proj = nn.Linear(d_model, d_model)

    def __call__(self, x: mx.array, mask=None):
        B, T, C = x.shape

        q = self.q_proj(x).reshape(B, T, self.num_heads, self.d_head).transpose(0, 2, 1, 3)
        k = self.k_proj(x).reshape(B, T, self.num_heads, self.d_head).transpose(0, 2, 1, 3)
        v = self.v_proj(x).reshape(B, T, self.num_heads, self.d_head).transpose(0, 2, 1, 3)

        # Scaled dot-product attention
        scores = (q @ k.transpose(0, 1, 3, 2)) / self.scale

        if mask is not None:
            scores = scores + mask

        weights = mx.softmax(scores, axis=-1)
        out = (weights @ v).transpose(0, 2, 1, 3).reshape(B, T, C)
        return self.out_proj(out)

4. LLM 서빙 도구와 실전 벤치마크

llama.cpp + Metal 백엔드

llama.cpp는 현재 Apple Silicon에서 LLM을 돌리는 가장 검증된 방법입니다. Metal 백엔드를 통해 GPU를 활용합니다.

# llama.cpp 빌드 (Metal 지원)
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
cmake -B build -DLLAMA_METAL=ON
cmake --build build --config Release -j

# M4 Pro에서 Llama 3.1 8B 실행
./build/bin/llama-cli \
  -m models/llama-3.1-8b-q4_k_m.gguf \
  -p "Explain transformer architecture" \
  -n 200 \
  --n-gpu-layers 999  # 모든 레이어를 GPU(Metal)로 오프로드
# 예상 출력: ~45-50 tok/s (M4 Pro 48GB)

# Metal 디버그 정보 확인
GGML_METAL_LOG_LEVEL=1 ./build/bin/llama-cli -m model.gguf ...

Ollama: llama.cpp를 감싼 프로덕션 레디 서버

# Ollama 설치 및 사용
brew install ollama
ollama serve  # 백그라운드 서버 시작

# 모델별 성능 (M4 Pro 48GB 기준 실측값)
ollama run llama3.2         # 3B, Q4_K_M: ~80-85 tok/s
ollama run llama3.1:8b      # 8B, Q4_K_M: ~45-50 tok/s
ollama run llama3.1:70b     # 70B, Q4_K_M: 메모리 부족 (48GB VRAM 기준)
# llama3.1:70b Q4_K_M = ~40GB → M4 Pro 48GB에서 간신히 가능, ~6-8 tok/s

# M4 Max 128GB에서
ollama run llama3.1:70b     # ~8-10 tok/s
ollama run llama3.3:70b     # ~8-10 tok/s (최신 70B)

# Python에서 Ollama API 사용
import ollama

response = ollama.chat(
    model='llama3.1:8b',
    messages=[{'role': 'user', 'content': 'Hello, explain RLHF'}]
)
print(response['message']['content'])

성능 비교표

모델양자화M4 Pro 48GBM4 Max 128GBRTX 4090 24GB
Llama 3.2 3BQ4_K_M~80 tok/s~100 tok/s~130 tok/s
Llama 3.1 8BQ4_K_M~45 tok/s~60 tok/s~110 tok/s
Llama 3.1 8BFP16~20 tok/s~35 tok/s~85 tok/s
Llama 3.1 70BQ4_K_M~6 tok/s~8 tok/sOOM (24GB 부족)
Llama 3.1 70BQ8OOM~4 tok/sOOM
Mistral 7BQ4_K_M~50 tok/s~65 tok/s~120 tok/s
Qwen2.5 72BQ4_K_MOOM~7 tok/sOOM

*실측 기준, 프롬프트 길이 및 KV cache 상태에 따라 변동


5. GGUF 양자화가 Apple Silicon에서 빛나는 이유

K-Quants 양자화 방식 이해

GGUF 형식의 Q4_K_M은 단순한 4-bit 양자화가 아닙니다. K-quants는 블록 단위로 서로 다른 precision을 적용하는 혼합 정밀도 방식입니다.

# Q4_K_M 양자화 과정 (간략화)
import torch

def quantize_q4_k(weight_tensor, block_size=32):
    """
    K-Quants: 블록 단위로 scale과 min 값을 FP16으로 저장
    실제 weight는 4bit integer로 저장
    """
    B, N = weight_tensor.shape
    num_blocks = N // block_size

    quantized_blocks = []
    scales = []
    mins = []

    for i in range(num_blocks):
        block = weight_tensor[:, i*block_size:(i+1)*block_size]

        # 블록별 최솟값과 최댓값 계산
        block_min = block.min(dim=-1, keepdim=True).values
        block_max = block.max(dim=-1, keepdim=True).values

        # 0-15 범위로 정규화 (4bit = 16개 레벨)
        scale = (block_max - block_min) / 15.0
        zero_point = -block_min / scale

        # 4bit 정수로 변환
        q = torch.round((block - block_min) / scale).clamp(0, 15).to(torch.uint8)

        quantized_blocks.append(q)
        scales.append(scale.to(torch.float16))
        mins.append(block_min.to(torch.float16))

    return quantized_blocks, scales, mins

# 역양자화 (추론 시)
def dequantize_q4_k(quantized, scales, mins):
    """4bit integer를 FP16으로 복원"""
    return quantized.float() * scales + mins

# 메모리 절약 계산:
# FP16 70B 모델: 70B * 2 bytes = 140 GB
# Q4_K_M 70B 모델: 70B * 0.5 bytes (approx) + overhead = ~40 GB
# 절약량: ~71%

x86 vs Apple Silicon에서 양자화 성능 차이

x86 CPU에서 양자화된 모델을 돌리면, 역양자화(dequantize) 과정에서 병목이 생깁니다. AVX-512가 있어도 4-bit 연산의 효율이 낮습니다.

반면 Apple Silicon GPU는:

  1. Metal shader로 최적화된 4-bit 연산 지원
  2. 유니파이드 메모리로 역양자화 후 바로 행렬 곱 가능 (별도 복사 불필요)
  3. INT8/INT4 연산 유닛이 GPU 내에 통합
# llama.cpp 양자화 타입 비교 (M4 Max 128GB, Llama 3.1 70B)
# Q2_K   : ~18GB, 품질 손실 큼, ~12 tok/s
# Q4_0   : ~35GB, 적당한 품질, ~8 tok/s
# Q4_K_M : ~42GB, 좋은 품질, ~8 tok/s (권장)
# Q5_K_M : ~52GB, 매우 좋은 품질, ~6 tok/s
# Q8_0   : ~70GB, 거의 FP16 수준, ~4 tok/s
# FP16   : ~140GB (128GB에 안 올라감!)

# 결론: Q4_K_M이 품질과 속도의 최적 균형점

6. M5 칩 예측 및 Apple AI 로드맵

M4 확인된 스펙 (2024년 기준)

M4:           10 CPU cores (4P+6E), 10 GPU cores, 38 TOPS ANE, 16-32GB
M4 Pro:       14 CPU cores (10P+4E), 20 GPU cores, 38 TOPS ANE, 24-64GB
M4 Max:       14 CPU cores (10P+4E), 40 GPU cores, 38 TOPS ANE, 48-128GB
M4 Ultra:     28 CPU cores, 80 GPU cores, 76 TOPS ANE, 192GB (M4 Max * 2)
Memory BW:    M4=120GB/s, M4 Pro=273GB/s, M4 Max=546GB/s, M4 Ultra=819GB/s

M5 전망 (2025-2026 예상)

업계 분석가들의 예측을 종합하면:

예상 M5 스펙 (N3P 공정, 2025 후반):
- TSMC 3nm N3P 공정 (M4 N3E 대비 ~15-20% 전력 효율 향상)
- CPU: M5 Pro 기준 20 cores (12P + 8E) 예상
- GPU: M5 Max 기준 50 GPU cores 예상
- Neural Engine: 50+ TOPS 예상
- 메모리: M5 Max 최대 192GB (현재 M4 Max 128GB에서 증가)
- 메모리 대역폭: M5 Max 기준 700+ GB/s 예상 (M4 Max 546 대비 ~30% 증가)

M5의 가장 큰 관심사는 메모리 용량 확장입니다. 192GB M5 Max가 나온다면 Llama 3.1 70B를 Q8으로 (~70GB), 혹은 FP16으로 (~140GB) 넉넉하게 올릴 수 있게 됩니다.

Apple의 On-Device AI 전략

Apple은 Private Cloud Compute(PCC)와 on-device 모델 사이의 하이브리드 전략을 추구합니다. iPhone 16에 3B 파라미터의 Apple Intelligence 모델이 탑재되어 있고, Mac에서는 더 큰 모델을 실행합니다.

Apple Intelligence 아키텍처 (추측):
User Request
On-Device 모델 (3B, ANE 실행)
      (복잡한 요청만)
Private Cloud Compute (더 큰 모델, Apple Silicon 서버)

LLM 학습 측면에서는 여전히 NVIDIA H100/H200 대비 뒤처집니다. M4 Ultra의 76 TOPS ANE는 H100의 3958 TOPS Tensor Core 대비 비교가 안 됩니다.


7. 실전 설정: Mac에서 로컬 LLM 환경 구축

MLX-LM으로 모델 돌리기

# mlx-lm 설치
pip install mlx-lm

# Hugging Face 모델을 MLX 형식으로 변환 후 실행
python -m mlx_lm.convert \
  --hf-path meta-llama/Llama-3.1-8B-Instruct \
  --mlx-path mlx_models/llama-3.1-8b \
  --quantize \
  --q-bits 4  # 4-bit 양자화

# 변환된 MLX 모델 실행
python -m mlx_lm.generate \
  --model mlx_models/llama-3.1-8b \
  --prompt "Explain attention mechanism" \
  --max-tokens 500
# Python에서 MLX-LM 직접 사용
from mlx_lm import load, generate

model, tokenizer = load("mlx-community/Llama-3.1-8B-Instruct-4bit")

prompt = "You are a helpful assistant. Explain what makes Apple Silicon unique for AI inference."

response = generate(
    model,
    tokenizer,
    prompt=prompt,
    max_tokens=500,
    verbose=True,     # 토큰 생성 속도 출력
)

메모리 사용량 모니터링

# Apple Silicon 메모리 및 GPU 사용량 확인
# Activity Monitor > Memory 탭 열기, 또는:

# powermetrics로 GPU 활용률 확인 (root 필요)
sudo powermetrics --samplers gpu_power -i 500 -n 5

# asitop (써드파티 툴, pip install asitop)
sudo asitop
# CPU/GPU/ANE 활용률, 메모리 대역폭, 전력 소비를 실시간으로 확인 가능

8. Apple Silicon vs NVIDIA: 현실적인 선택 기준

비교표

사용 케이스Apple SiliconNVIDIA GPU추천
로컬 LLM 실험 (70B 이하)M4 Max 128GB 가능24GB VRAM으로 불가Apple Silicon
로컬 LLM 실험 (8B 이하)M4 Pro로 충분RTX 4090도 OK취향/예산
프로덕션 서빙 (대규모)비효율적A100/H100 최적NVIDIA
모델 파인튜닝 (70B)매우 느림8x H100 권장NVIDIA
배터리/이동성맥북에서 15-20W데스크탑 300-400WApple Silicon
메모리 용량 (단일 기기)M4 Ultra 192GBH100 SXM 80GBApple Silicon
비용 효율 (추론)맥북 $3,000-6,000RTX 4090 $1,600+ 전기세비슷
소프트웨어 생태계제한적 (빠르게 성장)CUDA 압도적NVIDIA
CUDA 코드 호환성불가완전 지원NVIDIA

솔직한 결론

Apple Silicon이 우월한 경우:

  • 혼자 개발하면서 큰 모델(30B-70B)을 로컬에서 돌리고 싶을 때
  • 이동하면서 작업해야 할 때
  • 배터리 효율이 중요할 때
  • 이미 맥 생태계에 있을 때

NVIDIA를 선택해야 하는 경우:

  • 프로덕션 환경에서 처리량(throughput)이 중요할 때
  • 모델 학습, 파인튜닝이 주 작업일 때
  • PyTorch/CUDA 생태계의 최신 기능을 바로 써야 할 때
  • 팀 전체가 동일한 개발 환경이 필요할 때

개인적으로는, ML 엔지니어라면 Mac에 Apple Silicon + 클라우드 A100/H100 접근권을 조합하는 것이 2026년 현재 가장 실용적인 선택입니다. 로컬 개발과 실험은 Mac에서, 대규모 훈련과 프로덕션은 클라우드에서.


마치며

Apple Silicon의 UMA는 단순한 마케팅 문구가 아닙니다. PCIe 병목을 제거하고, 대용량 메모리 풀을 제공하며, 낮은 전력으로 실용적인 LLM 추론을 가능하게 합니다. llama.cpp + Metal + GGUF Q4_K_M의 조합은 2026년 현재 Mac에서 LLM을 돌리는 가장 검증된 방법입니다.

M5 칩이 나오고 메모리 대역폭이 700+ GB/s에 도달하면, 단일 기기에서 더 빠른 70B 모델 추론이 가능해질 것입니다. Apple이 MLX 생태계를 계속 키워간다면, 미래의 Apple Silicon은 더욱 매력적인 로컬 AI 추론 플랫폼이 될 것입니다.

CUDA와 NVIDIA의 오랜 헤게모니에 처음으로 실질적인 대안이 생겼다는 점에서, Apple Silicon의 등장은 ML 엔지니어 모두에게 좋은 일입니다.