gpumode · 강의 아카이브
《GPU Mode》 L055 2024 High priority transcript · failed

Modular's unified device accelerator language — Mojo

Modular (Chris Lattner / 전 LLVM, Swift, Tensorflow 핵심) 가 만든 Mojo 라는 새 언어 — Python 의 surface syntax 를 유지하면서 MLIR 위에서 lowering 해 CPU + GPU + 다양한 가속기 를 같은 코드로 다룬다는 야심. 그 디자인의 의도와 실제 도달한 위치, 그리고 CUDA/Triton 과의 차이의 학습 노트. 본 페이지는 transcript 가 실패해 Modular 공식 문서, Chris Lattner 의 talk, Mojo 공개 코드로 재구성됐다 — speaker 정보가 누락되어 비워둠.

Mojo MLIR unified language CPU+GPU Python interop SIMD parametric metaprogramming vs Triton/CUDA
강의 번호
L055
스피커
missing
Transcript
failed · 본 노트는 재구성
학습 우선순위
High · 차세대 도구 후보
§ 01강의가 풀려는 문제· why this lecture exists

“CUDA, Metal, ROCm, OneAPI 가 다 따로인 시대” 의 답을 찾는 시도

ML 가속기 생태계는 — 같은 알고리즘을 NVIDIA 위에서 (CUDA), Apple 위에서 (Metal), AMD 위에서 (ROCm), Intel 위에서 (OneAPI), Google TPU 위에서 (XLA) 따로따로 짠다. 한 언어로 모두를 다룬다 는 야심을 가진 도구가 Mojo — 그 의도를 어디까지 실현했는가.

강의의 출발 질문 셋.

  1. 왜 또 새 언어인가 — Triton 도 있고 OpenAI 가 밀고 있는데. CUDA 도 표준인데. Mojo 가 뭐가 다른가?
  2. MLIR 기반 컴파일 파이프라인 이 무엇이고 어떤 의미인가?
  3. 실전에서 쓰이고 있는가 — Modular 의 inference engine MAX 가 실제 production 에서.

본 노트는 transcript 실패로 — Modular 공식 문서 (docs.modular.com/mojo), Chris Lattner 의 talk (LLVM dev meetings, ASPLOS), Mojo 공개 standard library 의 코드로 재구성. speaker 정보가 누락되어 발표자 인용 형식 안 씀.

강의의 frame

Mojo 의 디자인은 두 축으로 본다. (1) 언어 자체의 야심 — Python 의 친숙함 + C++ 의 zero-overhead + Rust 의 안전성. (2) 컴파일 인프라의 야심 — MLIR 위에서 모든 가속기를 같은 IR 로. 둘이 같이 가야 의미 있고, 둘이 따로 가면 “또 하나의 언어”.

“CUDA 가 NVIDIA 의 모델로 GPU 를 보고, Triton 이 OpenAI 의 모델로 GPU 를 본다면 — Mojo 는 MLIR 의 모델로 모든 가속기를 보려 한다.” 학습 노트 · 재구성
§ 02unified accelerator language 의 동기· 왜 또 새 언어

Modular 의 진단 — “Python 은 너무 느리고, C++ 은 너무 어렵고, CUDA 는 너무 lock-in”

Mojo 가 풀려는 핵심 문제는 “하나의 언어로 high-level Python 과 low-level kernel 을 모두” — 즉 two-language problem 의 해소. ML 엔지니어가 Python 으로 모델을 짜고, kernel 엔지니어가 CUDA 로 가속기를 짜는 두 세계가 분리된 자리.

Python
생산성 ↑↑ — but interpreter 느림. PyTorch 가 Python 인 이유의 본질.
C++
성능 ↑↑ — but 인지적 부담 큼. CUDA, ROCm, oneAPI 의 base.
Mojo
Python surface + C++ 성능. 같은 파일 안에 두 layer. ML 엔지니어 ↔ kernel 엔지니어 경계 흐림.

Mojo 의 디자인 결정.

  • Python superset — 기존 Python 코드가 그대로 동작 (목표). Python 사용자가 점진적으로 진입.
  • strong type system — Python 의 dynamic 의 위에 강한 type 을 얹는다. 컴파일 시점 type 결정으로 zero-overhead 가능.
  • SIMD 가 first-class — Python 에는 없는 SIMD vector type. CPU/GPU 의 vector 명령어 직접 매핑.
  • ownership / lifetime — Rust 의 borrow checker 와 비슷. 메모리 안전성 + zero-cost.
  • parametric metaprogramming — C++ template 같지만 더 일반적. type 과 const 를 generic.
  • MLIR 위 lowering — 코드를 MLIR 로 컴파일. CPU/GPU/TPU 별 backend 가 같은 IR 위.
# Mojo 코드 예시 — Python 처럼 보이지만 type 명시
fn matmul(
    a: Tensor[DType.float32],
    b: Tensor[DType.float32]
) -> Tensor[DType.float32]:
    var c = Tensor[DType.float32](a.shape[0],
                                       b.shape[1])
    @parameter
    fn compute_row(i: Int):
        for j in range(b.shape[1]):
            var acc: Float32 = 0
            for k in range(a.shape[1]):
                acc += a[i, k] * b[k, j]
            c[i, j] = acc
    parallelize[compute_row](a.shape[0])
    return c

위 코드의 인상 — Python 과 거의 같지만 fn, var, type annotation, @parameter, parallelize 같은 추가 요소. 이게 “Python superset” 의 의미. 같은 파일에서 dynamic Python 부분과 strict-typed kernel 부분이 섞인다.

§ 03Mojo 언어 디자인· Python superset

같은 파일에 두 모드 — 점진적 진입

Mojo 의 의도된 사용법 — “Python 코드를 그대로 가져와서, hot loop 만 type 추가하면 빨라진다”. 사용자가 처음부터 모든 걸 새로 배울 필요 없이 점진적으로 깊이 들어갈 수 있게.

L0 Python 그대로 — 기존 .py 파일을 .mojo 로 rename 만. interpreter 모드로 동작 (CPython 호환). 빨라지지 않지만 동작은 동일. 호환성
L1 fn 추가def 대신 fn 으로 정의. type 명시 강제. AOT 컴파일 가능. C 와 비슷한 속도. 10~100×
L2 SIMD vectorizationSIMD[DType, width] type 사용. CPU vector instruction 직접 매핑. 메모리 alignment 까지 통제. + 4~8×
L3 parallelizeparallelize[fn] 으로 multi-thread 실행. 같은 코드를 thread pool 위에서. + N cores
L4 GPU dispatch@target("nvptx") 같은 attribute. 같은 함수가 GPU 위에서 컴파일 + 실행. + GPU
두 모드의 분리 — def vs fn

Mojo 는 같은 파일에 두 모드를 둔다. def 는 dynamic Python 호환 함수 — 자유롭지만 느림. fn 은 strict-typed Mojo 함수 — type 강제, 컴파일, 빠름. 사용자가 명시적으로 어느 모드를 쓸지 결정.

type 시스템의 한 가지 흥미로운 점 — parametric type. C++ 의 template 과 비슷하지만 type 과 const value 를 같은 mechanism 으로 generic. SIMD[DType.float32, 8] 의 8 은 compile-time const — vector width 가 type 의 일부.

“Mojo 의 design 은 ‘Python 사용자가 한 줄씩 더 깊이 들어갈 수 있게’ 의 사다리. CUDA/Triton 처럼 ‘처음부터 새 언어’ 가 아님.” 학습 노트 · 재구성
§ 04MLIR 기반 컴파일 파이프라인· lowering 사다리

같은 IR 위에서 모든 target 의 backend 를 만든다

Mojo 의 진짜 차별점은 — MLIR 위에서 동작한다는 점. MLIR 은 LLVM 프로젝트 안의 “여러 dialect 를 같이 다루는 IR 인프라”. Mojo 는 자기 dialect 를 정의하고, 그 dialect 가 MLIR 의 다른 dialect (gpu, nvgpu, vector, linalg 등) 로 lowering.

FIG · Mojo → CPU/GPU 의 lowering 사다리MLIR pipeline
L0 Mojo source.mojo 파일. Python-like syntax + type system. human
L1 Mojo dialect — high-level IR. type-aware. parametric 가 그대로 유지. MLIR
L2 linalg / tensor / vector dialect — high-level tensor 연산을 generic IR 로. 여기서 fusion, tiling, layout 결정. MLIR
L3 target-specific dialect — CPU 면 LLVM dialect + vector intrinsics. GPU 면 nvgpu / rocdl / spirv. 분기. MLIR
L4 LLVM IR — 최종 generic IR. MLIR 에서 LLVM 으로 lowering. LLVM
L5 machine code — x86 / ARM / NVPTX / amdgcn. native binary. native
중간 단계의 IR (linalg, vector) 가 generic 이라서 — 새 가속기 backend 를 추가할 때 위 layer 를 다시 안 만들어도 된다. MLIR 의 본질적 가치.

MLIR 의 의미 — “여러 IR 를 한 frame 안에서”. dialect 라는 단위로 nested IR 를 두고, 한 단계의 lowering 이 다른 dialect 로 점진적으로 변환.

이게 왜 의미 있는가 — 새 가속기 backend 를 만들 때 새 언어를 만들 필요가 없다. MLIR 의 한 dialect 를 정의하고, 그 dialect 가 기존 generic dialect 로 lowering 하면 — 자동으로 위에서 내려오는 ML 워크로드 모두를 받을 수 있음.

CUDA vs MLIR 의 layer 차이

CUDA 는 single-target language — NVIDIA GPU 만 지원. Mojo (MLIR) 는 — 같은 source 가 여러 backend 로 동시에. 이론적으로는. 실제로는 backend 별로 추가 작업 필요.

CPU
x86 SSE/AVX, ARM NEON. LLVM 의 vector intrinsics.
NVIDIA GPU
nvgpu dialect → NVPTX → SASS. MMA / async copy 직접 표현 가능.
AMD GPU
rocdl dialect → amdgcn. CDNA architecture 지원.
Apple Silicon
Metal Performance Shaders 위 backend (계획).
Google TPU
XLA HLO 와의 interop (계획).
기타
Intel oneAPI, RISC-V vector — MLIR community 가 dialect 추가.
§ 05CPU + GPU 같은 코드· target-specific 분기

“같은 알고리즘이 두 hardware 에서 다른 모양으로 도는” 자리

Mojo 의 약속 — 같은 source 가 CPU/GPU 모두 컴파일된다. 실제로는 두 가지 패턴. (1) 동일 코드 — generic 한 vectorize/parallelize 가 CPU/GPU 별로 다른 backend 로 lowering. (2) target-specific 분기 — @target("gpu") 으로 GPU-only 코드 작성.

현실의 한계

“같은 코드” 가 정말 같으려면 — algorithm 이 두 hardware 에서 같은 모양이어야 함. matmul 같은 경우 가능. 그러나 attention 같은 경우 — GPU 의 SRAM 위에서 SOTA 인 알고리즘 (FA) 은 CPU 위에선 다른 모양이 더 좋음 (block matmul + bigger cache). 결국 두 hardware 에서 진짜 SOTA 를 내려면 target-specific 코드 가 필요. Mojo 도 예외 아님.

# 같은 코드가 CPU 와 GPU 양쪽에서 컴파일
fn vector_add[size: Int](a: SIMD[DType.float32, size],
                       b: SIMD[DType.float32, size]
                       ) -> SIMD[DType.float32, size]:
    return a + b

# GPU only — target attribute
@target("nvptx")
fn matmul_tiled_gpu(...):
    # shared memory · sync · MMA 지원
    var tile = stack_alloc[shared, ...]()
    ...

# CPU only — 다른 algorithm
@target("x86_64")
fn matmul_tiled_cpu(...):
    # cache-aware blocking · AVX
    ...

실전 모델의 일반적 분기.

  • elementwise / pointwise — 같은 코드가 양쪽에서 거의 그대로 동작. vectorize + parallelize.
  • matmul — 알고리즘은 같지만 tile size 와 layout 이 다름. @parameter 로 target-aware tile 결정.
  • reduction (sum, max) — CPU 는 SIMD horizontal reduction, GPU 는 warp shuffle. 분기 필요.
  • attention — Flash Attention 같은 알고리즘은 GPU 의 SRAM/HBM 차이 활용. CPU 위에선 다른 알고리즘이 더 빠름.

Mojo 의 가치는 — 분기 자체가 아니라 “분기의 인프라 가 통합” 되어 있다는 점. 사용자는 같은 type system, 같은 lifetime, 같은 syntax 로 두 코드를 짠다. 새 언어 두 개 안 배워도 된다.

§ 06Python interop· 기존 생태계 활용

NumPy, PyTorch, HuggingFace 를 그대로 import

Mojo 의 가장 실용적 결정 — CPython 의 모든 라이브러리를 그대로 import. from python import Python, 그 다음 NumPy 든 PyTorch 든 그대로. 새 생태계를 zero 부터 만들 필요 없음.

# Mojo 안에서 Python 모듈 import
from python import Python

fn main():
    np = Python.import_module("numpy")
    arr = np.array([1, 2, 3])
    var mean = arr.mean()
    print(mean)            # 2.0

    # Pytorch 도 그대로
    torch = Python.import_module("torch")
    t = torch.randn(10, 10)
    print(t.shape)

이 interop 의 의미 — 사용자가 “기존 PyTorch 코드의 hot loop 만 Mojo 로” 쓸 수 있음. 점진적 진입의 핵심 자리.

그러나 한계 — Python 객체와 Mojo 객체는 boundary 에서 변환. numpy.ndarray → Mojo Tensor 는 zero-copy 가능 (DLPack), 그러나 일반 Python 객체는 복사. boundary 가 hot path 에 있으면 손해.

이상적 사용 패턴

(1) 기존 Python 코드의 outer 부분은 그대로. (2) hot kernel 만 Mojo fn 으로. (3) numpy/torch tensor 의 내부 buffer 를 zero-copy 로 받고 결과 buffer 도 zero-copy 로 돌려줌. 이 boundary 가 깔끔하게 안 잡히면 interop 비용이 큼.

다른 시도 — Modular 의 MAX engine. PyTorch / TensorFlow 모델을 받아서 Mojo 로 컴파일된 inference engine 으로 변환. 사용자는 Mojo 안 봐도 가능. 즉 “Mojo 가 뒤에서 도는 것” 도 의도된 사용 패턴.

§ 07채택 사례· 실전 사용 자리

Mojo 가 실제로 도는 자리

Mojo 의 채택 단계는 — language 가 2023 년에 발표되었고, 2024 년에 open source 일부, 2025 년 시점에서도 “early adopter” 단계. 실전 production 사용 사례는 많지 않지만 몇 군데 명확히 있다.

MAX inference engine
Modular 자사의 production 추론 엔진. PyTorch/TF/ONNX 모델을 받아 Mojo lowering 으로 가속. 가장 큰 채택 사례.
benchmark kernel 들
matmul, conv, attention — Mojo 로 짠 SOTA 수준 kernel 의 reference 구현. 학습 자료로.
stdlib
Mojo standard library — Python stdlib 의 핵심 functionality 를 Mojo 로 재구현 중. 진행 중.
community kernel
초기 사용자들이 짠 kernel 들. matrix transpose, softmax, layernorm 등.
교육 자료
Mojo 의 “Mandelbrot in Mojo” 같은 tutorial — 점진적 최적화의 표준 예제.
미래 자리
PyTorch 와 통합 — torch.compile 의 backend 로 Mojo. 직접적 production 침투의 가장 빠른 길.
2025 년 시점의 위치

Mojo 는 — “기술적으로는 흥미롭지만 production 도입은 일부”. CUDA / Triton / PyTorch 의 강력한 incumbent 가 있어 — 새 language 의 진입 장벽이 큼. 그러나 MAX engine 이 충분히 빠르다면 — 사용자가 Mojo 를 직접 보지 않고도 그 효과를 누릴 수 있음. 이 “invisible adoption” 이 가장 가능성 높은 시나리오.

“Mojo 의 진짜 시험대 — 누가 PyTorch 를 두고 Mojo 를 직접 쓸 것인가. MAX 처럼 ‘뒤에 도는 도구’ 로 정착할 가능성이 더 높을 수 있다.” 학습 노트 · 재구성
§ 08Triton / CUDA 와 차이· 서로 다른 슬롯

Mojo 가 들어가려는 자리는 Triton 과 다르다

Mojo 와 Triton/CUDA 를 “경쟁자” 로 봐야 하는지 — 사실 셋이 차지하는 자리가 다르다. 같이 쓰일 수 있는 도구들.

CUDATritonMojo
target NVIDIA GPU only NVIDIA + AMD (실험적) CPU + GPU (NVIDIA, AMD, ...) + 미래의 가속기
언어 surface C++ + extensions Python embedded DSL (tile-level) Python superset
통제 단위 thread (1인칭) tile (block-level) function + SIMD + parallel
컴파일 인프라 nvcc (closed) MLIR (Triton dialect) MLIR (Mojo dialect)
end-to-end 워크플로 kernel만 kernel만 전체 program (kernel + host)
학습 곡선 매우 가파름 중간 완만 (Python 친숙)
성숙도 17년+ production 5년 production 2년, early adopter
Mojo 의 차별점 정리

(1) 전체 program — kernel 뿐 아니라 host code 까지. (2) cross-target — CPU + GPU + 미래의 가속기. (3) Python superset — 점진적 진입. 이 셋이 합쳐지는 지점에서 — Mojo 가 차지하려는 자리는 “PyTorch + Triton + CUDA 가 셋 다 들어가야 하는 자리를 한 언어로”.

그러나 — “하나로 다 한다” 는 야심은 종종 “여러 자리에서 약간씩 부족하다” 로 끝난다. Triton 의 GPU kernel 을 Mojo 로 짜는 것이 진짜 Triton 만큼 빠른가? CUDA 의 디테일한 통제가 Mojo 에 다 있는가? 산업의 검증이 더 필요한 자리.

§ 09한계와 비판점· caveats

Mojo 가 도전하는 자리에서 부딪히는 현실

  1. open source 의 시기 — 2024 년에 일부 open. 핵심 컴파일러는 closed 였다가 점진적 공개. open community 의 contribution 이 약함.
  2. incumbent 의 강함 — PyTorch + CUDA 의 생태계가 너무 크고 잘 동작 중. 새 언어가 비집고 들어갈 자리가 좁음.
  3. Python superset 의 약속의 어려움 — 일부 dynamic Python 의 패턴 (eval, monkey-patching, decorators의 일부) 은 type system 과 어긋남. “모든 Python 이 그대로 도는” 약속이 깨질 수 있음.
  4. MLIR 의 추상 비용 — MLIR 의 generic 한 인프라는 강력하지만 — 새 backend 추가에 여전히 큰 작업 필요. “자동으로 새 가속기 지원” 은 마케팅 측면.
  5. Triton 과의 비교에서 — Triton 의 autotuning + tile abstraction 이 GPU kernel 작성에서 충분히 쉬움. Mojo 의 추가 가치가 GPU kernel 만 보면 작음.
  6. CUDA C++ 과의 비교에서 — CUDA 의 raw 통제와 성능 매칭이 어려움. NVIDIA 의 hardware 디테일을 Mojo 가 다 노출하는지.
  7. tooling 부족 — IDE 지원, debugger, profiler 가 PyTorch/CUDA 에 비해 약함.
  8. 채택의 chicken-and-egg — 큰 사용자가 Mojo 코드를 안 짜면 Mojo stdlib 가 안 발달, stdlib 가 약하면 큰 사용자가 진입 안 함.
가장 가능성 높은 path

Mojo 가 직접 사용자에 노출되기보다 — MAX inference engine 같은 형태로 “뒤에서” 동작. 사용자는 PyTorch 모델을 그대로 쓰고, 그 모델이 Mojo 로 컴파일되어 빠르게 추론. 이 시나리오라면 — Mojo language 의 직접 채택은 부수적이고, MLIR 인프라의 가치가 본질적.

§ 10기억할 메모와 자료· key takeaways
Mojo 의 야심
Python superset + C++ 성능 + cross-target. two-language problem 해소.
def vs fn
def — Python 호환, dynamic. fn — strict type, 컴파일, 빠름. 같은 파일에 두 모드.
parametric type
SIMD[DType, width] 같이 type 과 const 를 함께 generic. C++ template 보다 일반적.
MLIR 위 lowering
Mojo dialect → linalg/tensor/vector → target dialect (nvgpu, rocdl, x86) → LLVM → native.
CPU + GPU
같은 source 가 양쪽에서 컴파일 가능. 하지만 SOTA 알고리즘은 보통 target-specific 분기 필요.
Python interop
CPython 모듈 그대로 import. PyTorch/NumPy 를 Mojo 안에서 직접 사용. 점진적 진입.
vs Triton/CUDA
Triton: tile-level GPU DSL. CUDA: NVIDIA GPU 만. Mojo: 전체 program + cross-target.
2025 년 위치
early adopter. MAX engine 이 가장 큰 production 사례. 직접 채택보다 “뒤에서” 도는 시나리오 가능성 높음.
§ 11다른 강의로 이어지는 길· connections

같은 자리를 다른 각도에서 다루는 강의들

§ 12열린 질문· open questions

원본 자막 실패 + speaker 정보 누락으로 비워둔 자리들

검증 메모

Mojo 는 빠르게 발전 중인 언어 — 본 노트의 spec 과 사용 패턴은 강의 시점 (2024) 의 모습. 2025 년 이후 — open source 진행, language 의 stable spec 도달, MAX engine 의 production 채택 — 이 셋의 진행에 따라 본 노트의 평가가 갱신될 필요. Mojo 공식 docs 와 GitHub release notes 를 직접 확인 권장.

← Lecture 054 Small RL Models with LeanRL Lecture 056 → Kernel Benchmarking Tales