Triton 의 강점은 “compiler 가 알아서” 였다 — BLOCK_SIZE, num_warps, num_stages 만 정하면 나머지는 lowering 이 풀어준다. 그러나 Hopper/Blackwell 의 새 기능 (TMA · async tensor core · warp specialization) 은 compiler heuristic 만으로는 못 짠다. TLX (Tile-Level eXtensions / Triton Low-level eXtensions) 는 expert 사용자가 그 자리에 직접 손을 대게 해주는 layer. transcript 가 실패해서 본 노트는 facebookexperimental/triton:tlx branch 와 일반 GPU kernel 도메인 지식 기반.
강의의 출발점. Triton 의 lowering 은 “compiler heuristic 이 충분히 똑똑하다” 는 가정 위에 산다. 그러나 H100 의 진짜 성능은 — warp specialization · async tensor core · TMA · multi-stage pipelining 같은 새 기능을 직접 조합해야 나온다. 이게 compiler 자동화의 한계.
“Triton 은 80% 의 사용자에게 80% 의 성능을 준다. 나머지 20%—frontier kernel의 마지막 20% 는 compiler 가 못 한다. TLX 는 그 자리에 expert 가 손을 댈 수 있게 한다.”
강의에서 자주 인용되는 예 — flash attention 3. CUTLASS 로 짠 hand-tuned 버전이 H100 에서 700+ TFLOP/s. Triton 으로 같은 로직을 짜면 60–70% 수준. 그 차이가 warp specialization · async tensor core 의 직접 조작에서 온다. TLX 가 그걸 Triton 안에서 가능하게 한다.
TLX 의 표준 풀네임은 “Triton Low-level eXtensions” 또는 “Tile-Level eXtensions” 로 불린다 — 본 노트는 facebookexperimental/triton 의 tlx branch 의 README 표현을 따른다. 강의 시점에 정확한 이름을 영상에서 확인 필요. 둘 다 같은 의도 — Triton 의 high-level 자동화 위에 hardware-near 의 직접 제어 layer.
TLX repo 의 README 가 정리하는 4영역. Triton 의 high-level 추상 위에 추가되는 hardware-near 도구들.
tlx.local_alloc() — shared/tensor memory 에 buffer 직접 할당. tlx.local_load/local_store 로 layer 간 직접 transfer. compiler 가 알아서 풀던 자리에 사용자가 손.
token = tlx.async_copy(...) 후 tlx.wait(token).
tlx.async_tasks(...) — block 의 thread 를 task 별로 분할. 어떤 warp 는 load 만, 어떤 warp 는 compute 만. Hopper/Blackwell 의 핵심 기법.
이 4영역의 공통점 — Triton 의 자동화를 부분적으로 끄고, 사용자가 명시적으로 통제. 그래서 TLX 코드는 vanilla Triton 보다 길고 복잡하지만, compiler 가 못 잡는 자리를 잡는다.
TLX 는 standalone 라이브러리가 아니다. facebookexperimental/triton 의 tlx branch 안에 들어간 확장. import triton.language as tl 옆에 import triton.language.extra.tlx as tlx 같은 형태로 사용. Triton 본가와 별개로 진화하는 실험 가지.
TLX 가 가능하게 하는 핵심 — H100 의 hardware feature 를 Triton 안에서 직접 호출. CUTLASS 의 정신을 Python 으로.
vanilla Triton 도 H100 위에서 도는 PTX 를 생성한다. 그러나 그 PTX 가 이 4가지 feature 를 충분히 활용하지 않는다. compiler 가 conservative 하게 schedule 하기 때문. TLX 는 — “여기는 async, 여기는 producer, 여기는 consumer” 를 사용자가 직접 적게 한다.
1. frontier kernel (flash attention, GEMM-K) — 마지막 20% 성능이 의미 있을 때. 2. Hopper/Blackwell 전용 — 새 hardware 의 feature 를 적극 활용. 3. kernel 라이브러리 저자 — 한 번 짜고 많이 호출되는 코드. 일반 모델 코드는 vanilla Triton 이 더 효율적.
TLX repo 의 첫 example — pipelined GEMM. vanilla Triton 으로 짜면 compiler 가 일부 pipeline 을 만들지만, TLX 로 직접 짜면 N-stage 의 timing 을 사용자가 통제.
# pseudo-code — TLX pipelined GEMM 의 골격
@triton.jit
def gemm_kernel(...):
# 3-stage shared memory buffer
a_buf = tlx.local_alloc(
shape=(3, BM, BK),
dtype=tl.float16,
)
b_buf = tlx.local_alloc(
shape=(3, BK, BN),
dtype=tl.float16,
)
# warmup — 첫 2 tile 미리 load
tok0 = tlx.async_copy(a_ptr, a_buf[0])
tok1 = tlx.async_copy(a_ptr+BK, a_buf[1])
acc = tl.zeros(...)
for k in range(K // BK):
slot = k % 3
next_slot = (k + 2) % 3
# 다음 tile async load 시작
tok = tlx.async_copy(
a_ptr + (k+2)*BK, a_buf[next_slot]
)
# 현재 tile 의 load 완료 대기
tlx.wait(toks[slot])
# mma — async tensor core
acc = tlx.async_mma(
a_buf[slot], b_buf[slot], acc
)
tlx.wait_all()
tl.store(c_ptr, acc)
이 패턴이 가르치는 것 — async + buffer rotation이 multi-stage pipelining 의 본질. compiler 가 못 보던 timing 을 사용자가 직접 표현. 실제 코드는 더 길지만 (boundary 처리, prologue/epilogue) 핵심은 위 골격.
TLX 의 가장 중요한 example. flash attention 의 새 변형이 — TLX 의 async_tasks 로 자연스럽게 표현. 한 block 의 warp 들을 두 그룹으로 분리.
이 분리가 만들어내는 효과 — memory 와 compute 가 다른 hardware unit 에서 동시에. CUTLASS 의 producer-consumer pattern 을 Triton 안에서.
# TLX warp specialization 의 골격
@triton.jit
def attention(...):
# shared memory + barrier 셋업
q_buf = tlx.local_alloc(...)
k_buf = tlx.local_alloc(...)
v_buf = tlx.local_alloc(...)
barrier = tlx.named_barrier()
with tlx.async_tasks() as tasks:
@tasks.task(num_warps=4)
def load_loop():
for i in range(N_BLOCKS):
tlx.tma_load(k_ptr, k_buf[i])
tlx.tma_load(v_ptr, v_buf[i])
barrier.arrive(i)
@tasks.task(num_warps=4)
def compute_loop():
for i in range(N_BLOCKS):
barrier.wait(i)
qk = tlx.async_mma(q_buf, k_buf[i])
p = softmax(qk)
acc = tlx.async_mma(p, v_buf[i], acc)
tl.store(out_ptr, acc)
이 코드의 mental model.
async_tasks 안에 두 def 함수 가 있음 — 두 warpgroup 의 코드.num_warps 로 지정된 warp 수를 차지.named_barrier 가 두 warpgroup 사이의 producer-consumer 동기.vanilla Triton 으로 같은 효과를 내려면 — compiler 가 알아서 warp 를 분리해줘야 한다. 그게 일반화하기 어려운 자리.
H100 의 tensor core 와 memory unit 은 hardware 레벨에서 별도 unit. SPMD 적인 코드 (모든 warp 가 같은 일) 면 한쪽이 항상 idle. warp specialization 으로 두 unit 을 동시에 굴리면 50% 의 hardware utilization 이 90%+ 로. 그게 flash attention 3 이 700+ TFLOP/s 를 내는 본질.
TLX 가 facebookexperimental 이라는 이름에서 드러나듯 아직 실험. 그러나 frontier kernel 영역에서는 흥미로운 자리.
TLX 의 가치는 한 kernel 이 매우 자주 호출되는 자리에서만 회수. flash attention 같은 자리는 LLM serving 의 hot path 라 회수 빠름. 일반 모델 코드는 vanilla Triton 또는 torch.compile 이 더 합리적. “너의 kernel 이 백만 번 도는가? 그렇다면 TLX. 아니면 vanilla.”
현재 TLX 는 facebookexperimental fork. 그러나 Triton 본가가 Hopper/Blackwell 지원을 깊게 가져가면 — TLX 의 일부 추상 (특히 async tensor core, warp specialization) 이 흡수될 가능성.
tl.async_tasks 같은 형태로 native 지원할 가능성.본 노트의 4영역 분류 (local memory · async ops · sync · warp specialization) 와 코드 예시는 facebookexperimental/triton 의 tlx branch README 의 정리를 기반으로 한다. 강의에서 다른 framing 이나 이름이 등장했을 수 있다 — 영상 직접 확인 후 보강 필요.