[Multi-Core & GPU Programming] Others 2

"Others 2"

[Compiler]

▣ Deep Learning Compiler
· TensorFlow XLA(Google)
· TensorRT(NVIDIA)
· TVM(Open Source)
· Glow(Meta)
· Triton(OpenAI)
→ Deep Learning Model 연산 최적화를 위한 서로 다른 Compiler

▣ Deep Learning Execution Model
· Deep Learning Framework는 Network를 Operator 단위로 하나씩 실행

> 한계점
① Interpreted Execution : Framework가 매번 다음 연산을 해석하면서 실행하여 속도↓
② 데이터를 여러 번 Scan : GPU에서는 연산보다 Memory 이동이 병목 (Conv → BatchNorm → ReLU 실행 시 Memory 반복 접근)
③ 개별 최적화 : 각 Operator마다 최적화된 구현 필요
→ Operator-By-Operator 실행은 단순하지만, Interpreted Execution Overhead와 Memory 접근 때문에 비효율적

▣ Compiler 처리
① Express Computation : Framework가 계산
② Intermediate Representation : Compiler가 중간 표현으로 변환
③ Reusable Optimization : 재사용 가능한 최적화 진행
④ Code Generation : HW에 맞는 Code 생성
→ IR 사용 시 Framework와 HW 분리 가능
    = PyTorch Model이든 TensorFlow Model이든 일단 IR로 바꾸면 공통 최적화 적용 가능

▣ Computation Graph As IR
· Deep Learning Model을 Computation Graph로 표현
· Operator Fusion : 연산을 합쳐 중간 결과를 Memory에 Load/Store하는 과정이 줄어들어 성능 향상
    Ex. 3개의 연산(conv2d → bn → relu)을 합쳐서 1개의 연산(fused-conv2d-bn-relu)으로 변경

** Computation Graph를 IR로 사용하면 Graph 수준 최적화 가능

▣ TensorFlow XLA Compiler(Google)
· 가속회된 선형대수 Compiler로 TensorFlow Model을 Tensor 연산을 표현하는 XLA HLO(High Level Operation)라는 IR로 변경

> XLA가 수행하는 주요 최적화
· Kernel Fusion : 여러 Kernel을 합쳐서 불필요한 Memory 접근↓
· Data Layout Optimization : 데이터 배치를 HW에 더 적합하게 바꿔서 성능↑
· Operator Dispatch Overhead↓ : Operator를 하나씩 호출하는 Overhead↓
· Loop Unrolling과 Vectorization 지원 : CPU/GPU에서 더 효율적으로 실행

** XLA : TensorFlow 계산 Graph를 분석해서 더 빠른 실행 Binary를 생성

▣ TensorRT(NVIDIA)
· 주로 학습보다는 추론을 빠르게 실행하는 데 사용

> TensorRT의 주요 기능
· Weight Quantization : 양자화를 통해 메모리 사용량과 연산량을 감소시켜 추론 속도 향상
· Kernel Fusion : Vertical Fusion(연속된 연산들을 병합)과 Horizontal Fusion(서로 독립적인 연산들을 병합) 지원

** TensorRT : NVIDIA GPU에서 DNN 추론을 매우 빠르게 실행하도록 Graph와 Kernel 최적화

▣ TVM(Open Source)
① 여러 Framework에서 Model을 받아서 계산 Graph로 만들고, 먼저 High-Level Graph Rewriting 수행
② Operator 수준에서 Tensor Expression으로 표현하고, Schedule Primitive를 이용해 어떻게 실행할지 결정
③ Machine Learning 기반 Auto Tuner를 사용해서 HW에 맞는 최적 Schedule 결정
④ LLVM IR, CUDA, METAL, OpenCL 같은 Backend를 통해 실제 실행 가능한 Module 생성

** TVM은 다양한 Framework와 다양한 HW를 연결하는 범용 Deep Learning Compiler

> TVM Stack High-Level View
① High Level Graph Rewriting : Computation Graph를 생성하고 최적화
    (Ex. Operator Fusion, Dead Code Elimination, Constant Folding 같은 Graph 수준 최적화 가능)
② Tensor Level Optimization & Scheduling & Tuning : 각 Operator 내부를 어떻게 계산할지 결정
    (Ex. Tiling, Loop Reordering, Vectorization, Memory Reuse 같은 최적화 수행)
③ Backend Code Generation : Target에 따라 NVCC, LLVM, OpenCL, VTA ISA, NPU ISA 등으로 Code 생성

** 새로운 HW가 나와도 Scheduler와 Backend를 추가하면 TVM Stack에 연결 가능

▣ Glow(Meta) - Graph Lowering
· Machine Learning Model을 HW 가속기에서 효율적으로 실행하는 것이 목적

① Glow Core가 입력으로 ONNX, PyTorch, C++ API 등을 받음
② PGO(Profile Guided Optimization)에서 실제 실행 통계를 수집하여 최적화
③ 적절한 Quantization 결정하여 최적화
④ Code Generation
⑤ 여러 Backend 실행

> Compilation Pipeline
· High-Level Optimizer : 그래프 수준 최적화 수행(Ex. 선형대수 수준에서 불필요한 연산을 제거하거나 병합)
· Low-Level Optimizer : 낮은 수준의 IR 최적화 수행(Ex. Buffer/Memory Reuse 같은 Memory 최적화)
· Accelerator Backend : 특정 HW에 맞게 Lowering하고 Code Generation 수행

** High-Level Graph를 점점 낮은 수준의 IR로 변환하면서 최적화하고, 마지막에는 CPU/Accelerator Backend에 맞는 코드 생성

[LLM]

· 최근 가장 핵심 AI Model인 Large Language Model을 빠르게 실행하는 것이 중요

▣ Decode-Only LLM
· Prefill : 사용자가 입력한 Prompt 전체를 Model이 한 번 읽고 처리 → 전체를 한 번에 처리
· Decode : 답변 Token을 하나씩 생성 → 이전에 생성한 Token에 의존하기 때문에 순차적으로 진행

▣ KV-Cache
· KV-Cache : 이전 Token들의 Attention 정보를 저장해두는 Memory 공간
    → 매번 이전 모든 Token의 K, V를 다시 계산하면 너무 느리기 때문에 사용
· Prefill : Initial Prompt의 모든 Token을 한 번에 처리 → 각 Token에 대해 Key와 Value를 계산해서 KV-Cache에 저장
· Decode : 새 Token을 한 생성할 때마다, 기존 KV-Cache를 참조 → 새로 생성된 Token도 다시 KV-Cache에 추가

▣ Sequential vs Parallel
· Prefill : Prompt Token들을 병렬 처리 가능
· Decode : Output Token을 순차 생성

▣ Basic Structure of LLM Inference
· LLM은 이전 Token들을 기반으로 다음 Token을 하나씩 생성하는 Auto-Regressive Architecture 사용
    (Ex. 입력 = I love you : I → also → love → you → <EOT>)
· Prefill Stage : GEMM 연산 주로 사용 (∵ 여러 Token들을 한 번에 처리하므로 입력이 Matrix 형태)
· Decode Stage : GEMV 연산 주로 사용 (∵ Token을 하나씩 처리하므로 입력이 Vector 형태)

 Important Operation GEMM/GEMV
· Prefill Stage : GEMM 연산이 Latency의 큰 부분 차지
· Context Length가 길어질수록 GEMM 비중 증가

· Decode Stage : GEMV 연산 중요
· Token을 하나씩 생성하기 때문에 Matrix-Vector 연산이 반복

▣ Roofline Model
· x축 : Arithmetic Intensity(= Memory에서 가져온 Byte당 연산량) / y축 : 성능(= Ops)
· 빨간색 영역 : Memory-Bound 영역 / 초록색 영역 : Compute-Bound 영역
· Decode : Arithmetic Intensity↓ → Memory-Bound에 근접
    ∵ Token 하나를 생성할 때 Weight 또는 KV-Cache를 많이 읽지만, 그에 비해 연산량은 상대적으로 작음
    ∴ Memory 접근, KV-Cache 관리, Bandwidth 최적화 중요
· Prefill : Arithmetic Intensity↑ → Compute-Bound에 근접
    ∵ 여러 Token을 한 번에 처리하므로 같은 Weight를 여러 Token 계산에 재사용 가능
    ∴ Tensor Core 활용, GEMM 성능, Tiling 중요

▣ Flash Attention
· 일반 Attention : S = QKT → P = softmax(S) → O = PV
    → Sequence Length가 길면 Attention Matrix 크기 증가 → HBM에 Load/Store 비용↑
· Flash Attention : Attention Matrix를 HBM에 크게 저장하지 않고, SRAM/On-Chip Memory를 활용해서 Block 단위로 계산

** Tiling + Fusion

· PyTorch Attention : Matmul, Mask, Softmax, Dropout, Matmul 등이 따로 실행
· Flash Attention : Fused Kernel로 묶어서 훨씬 적은 시간에 실행
→ 수학적으로 동일하게 계산하지만, Memory 접근을 크게 줄여서 빠르게 만드는 최적화

> Flash Attention Version
· Standard : 중간 Attention Matrix를 많이 Load/Store 하기 때문에 Memory 병목이 크고, GPU 계산 자원을 충분히 활용 X
· V1 : Tiling과 Fusion을 통해 성능 약간 증가
· V2 : Non-Matmul 연산을 줄이고, Warp Partitioning을 개선
· V3 : Hooper GPU에 맞게 최적화된 버전

[vLLM]

▣ Paged Attention
· LLM Decode에서는 이전 Token들의 KV-Cache를 계속 저장, But, 요청마다 문장 길이가 다르고, 생성되는 Token 수도 다름
  ∴ KV-Cache에 Memory를 연속된 큰 공간으로 잡으면 낭비↑
· Paged Attention : OS의 Virtual Memory처럼 KV-Cache를 Block/Page 단위로 나눠서 관리

△ KV-Cache Memory 낭비↓
△ 긴 Sequence 처리에 유리
△ 여러 요청을 Batch로 처리하기 용이
△ LLM Serving Throughput↑

** vLLM : LLM을 실제 서비스 환경에서 빠르고 효율적으로 Serving하기 위해 개발된 고성능 Inference Engine

▣ vLLM Optimization
· Chunked Prefill : 긴 Prompt를 한 번에 처리하지 않고 작은 Chunk로 나눠 처리하는 방식
    → Decode 요청과 Prefill 요청을 더 잘 섞어 Latency↓
· Dynamic Speculative Decoding : 작은 Draft Model이 먼저 여러 Token을 예측하고, 큰 Target Model이 이를 검증하는 방식
    → 맞게 예측된 Token은 한 번에 받아들일 수 있어서 Decode 속도↑
· Multi-LoRA Serving : 하나의 Base Model 위에 여러 LoRA Adapter를 붙여 서로 다른 요청을 처리하는 방식
    → 여러 LoRA 요청을 효율적으로 Batch 처리
· Hash-Based Automatic Prefix Caching : 여러 요청이 같은 Prefix를 공유할 때, 이미 계산한 KV-Cache를 재사용하는 방식
    → System Prompt가 같은 요청들이 많으면 Prefill 계산↓

[Reference]

· 15_more_notes_mgp_2026 (MGP) - Yongjun Park

댓글

이 블로그의 인기 게시물

[Mini-NPU RTL] NN Reference Model

[Mini-NPU RTL] TPU (Study Paper)