본문 바로가기
C.W.K.
Stream
Lesson 05 of 06 · published

MLX, PyTorch MPS, Core ML — 셋은 일이 달라

~16 min · comparison, pytorch-mps, coreml

Level 0호기심
0 XP0/51 lessons0/15 achievements
0/100 XP to next level100 XP to go0% complete

도구 셋, 맡은 일도 셋

여기서 기대치를 바로잡자. MLX를 가르치는 퀘스트니 앞으로 MLX 이야기가 많을 수밖에 없어. 그렇다고 Apple Silicon 위의 모든 머신러닝 일을 MLX 하나가 맡는 건 아니야. PyTorch MPS와 Core ML도 같은 생태계에 살고 있고, 셋의 역할을 섞으면 괜히 시간을 버려. 먼저 정직하게 나눠보자.

  • MLX — Apple의 연구 지향 배열 프레임워크. Python을 중심으로 하고 통합 메모리를 있는 그대로 활용해.
  • PyTorch MPS 백엔드 — CUDA 방식으로 짠 기존 PyTorch 코드를 Mac에서 돌릴 수 있게 연산을 Metal 호출로 번역해.
  • Core ML — 완성된 모델을 Apple 플랫폼 앱에 넣기 위한 실행 환경. Swift를 중심으로 iOS, macOS, watchOS, tvOS 배포를 맡아.

셋을 사람으로 비유하면

PyTorch MPS는 통역사야. CUDA용 PyTorch 코드를 되도록 적게 고쳐 Mac에서 돌리는 게 목표지. 익숙한 torch.tensor를 그대로 쓰고 device='cuda:0' 대신 device='mps'를 넣어. MPS 백엔드는 각 PyTorch 연산을 Metal Performance Shaders 호출로 바꿔줘. 이미 있는 PyTorch 코드베이스를 Mac에서 계속 다듬고 싶을 때 잘 맞아. 반대로 Apple Silicon 구조에 꼭 맞는 API를 원한다면 어색해. GPU가 별도 메모리를 가진 장치라는 CUDA의 세계관을 그대로 물려받았거든.

MLX는 원어민이야. API부터 통합 메모리 하드웨어의 모양을 따랐어. CPU와 GPU가 복사 없이 함께 일하고, 지연 실행 그래프와 함수 변환이 기본이라는 생각으로 출발해. Apple Silicon에서 새 프로젝트를 시작할 때 좋아. 하지만 MLX에 대응 기능이 없는 CUDA 전용 연산을 수십 개 쓰는 기존 PyTorch 모델을 그대로 돌리는 일에는 맞지 않아.

Core ML은 배포 담당이야. PyTorch나 TensorFlow 등에서 학습한 모델을 .mlpackage로 변환해 앱에 넣어. 모델 불러오기와 추론뿐 아니라 App Store 배포, 기기 안에서 지키는 개인정보, Vision·Speech 프레임워크와의 통합까지 맡아. 앱 기능으로 내보낼 때는 강하지만, 연구를 반복하거나 앱 출시와 별개로 모델을 자주 바꾸는 데는 느리고 답답해.

같은 행렬 곱셈도 입구가 다르다

아래에는 MLX와 PyTorch MPS로 같은 계산을 하는 코드가 있어. 둘 다 같은 mlx 환경에서 검증했어. 그 환경에 torch도 설치돼 있어서 MPS가 동작했거든. Core ML은 Python에서 보여줄 만한 행렬 곱셈 예제가 없어. Core ML의 Python 쪽은 배열 계산이 아니라 모델 변환을 위한 곳이야.

무엇을 골라야 할까

  • Apple Silicon에서 연구하거나 새 프로젝트를 시작한다 → MLX. 통역보다 원어민이 편해.
  • 기존 PyTorch 코드베이스를 Mac에서 개발한다 → PyTorch MPS. 다시 쓸 부분이 적지만 MPS가 지원하지 않는 연산은 미리 찾아야 해.
  • iOS, macOS, watchOS, tvOS 앱에 모델을 넣는다 → Core ML. App Store 배포와 개인정보 보호, 운영체제 통합이 중요하니까.
  • LLM을 로컬 HTTP 엔드포인트로 서빙한다 → MLX, 그중에서도 mlx-lm. 트랙 3에서 다뤄.
  • Python 없이 모델만 간단히 돌리고 싶다 → Ollama. v0.19부터 MLX 위에서 동작해. compare.lesson1에서 확인해.

속도 하나로 우열을 정하지 마

MLX가 모든 벤치마크에서 PyTorch MPS보다 빠르다고 말하는 게 아니야. 어떤 때는 MPS가 이기고, 어떤 때는 MLX가 이겨. MLX 릴리스 하나 사이에도 순위가 바뀔 수 있어. 중요한 건 셋이 서로 다른 일을 잘하도록 생겼다는 사실이야. 진영이 아니라 할 일로 골라.

Code

MLX에서 같은 행렬 곱셈·python
import mlx.core as mx

x = mx.random.normal((1024, 1024))
y = x @ x.T
mx.eval(y)
print("MLX     :", tuple(y.shape), y.dtype, mx.default_device())

# Verified output (2026-05-03):
#   MLX     : (1024, 1024) mlx.core.float32 Device(gpu, 0)
PyTorch MPS 백엔드의 같은 행렬 곱셈·python
# Requires PyTorch ≥ 2.0 with MPS support and macOS ≥ 12.3.
import torch

device = torch.device("mps" if torch.backends.mps.is_available() else "cpu")
x = torch.randn(1024, 1024, device=device)
y = x @ x.T
print("PyTorch :", tuple(y.shape), y.dtype, y.device)

# Verified output (2026-05-03, torch 2.11.0):
#   PyTorch : (1024, 1024) torch.float32 mps:0
Core ML 모델 변환 — 배포 쪽은 Swift가 맡아·python
# CoreML's Python surface is the conversion side, not array math.
# A typical workflow is: train in PyTorch, export to ONNX, convert to .mlpackage,
# then embed in a Swift app. Sketch only — not for execution here.
import coremltools as ct
import torch

# Suppose you have a trained PyTorch model `model` ...
# example_input = torch.rand(1, 3, 224, 224)
# traced = torch.jit.trace(model.eval(), example_input)
# mlmodel = ct.convert(
#     traced,
#     inputs=[ct.TensorType(shape=example_input.shape)],
#     compute_units=ct.ComputeUnit.ALL,   # CPU + GPU + Neural Engine
# )
# mlmodel.save("MyModel.mlpackage")

External links

Exercise

MLX와 PyTorch MPS의 행렬 곱셈 코드 블록을 모두 실행해. 두 번째는 환경에 torch가 있어야 하니 없으면 pip install torch를 쓰되, mlx 환경을 깨끗하게 두고 싶다면 별도 환경에서 해. 4096×4096 행렬 곱셈을 간단한 python -c 스크립트로 각각 세 번씩 재서 중앙값을 구해. 목적은 승자를 선언하는 게 아니야. 실행할 때마다 달라지는 값과, 결과가 행렬 모양·자료형·최근 릴리스에 따라 바뀐다는 사실을 느껴봐. 알아낸 점을 두 문장으로 정리해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.