NanoEuler: C와 CUDA로 밑바닥부터 구축한 GPT-2 규모의 LLM
NanoEuler: C와 CUDA로 밑바닥부터 구축한 GPT-2 규모의 LLM
NanoEuler는 C와 CUDA만을 사용하여 GPT-2급 언어 모델을 완전히 처음부터 구현한 연구 및 교육용 프로젝트입니다. PyTorch나 autograd와 같은 고수준 ML 라이브러리를 배제함으로써, 이 프로젝트는 직접 작성한 byte-level BPE tokenizer부터 supervised fine-tuning (SFT)에 이르기까지 모든 과정을 투명한 엔드투엔드 파이프라인으로 제공하며, 모든 과정은 엄격한 gradient checks를 통해 검증됩니다.
핵심 아키텍처 및 설계
NanoEuler는 소비자용 하드웨어에서 효율성을 극대화하기 위해 여러 현대적 LLM 최적화 기법을 활용하는 decoder-only transformer 아키텍처를 구현합니다. 모델은 아키텍처를 단순화하고 학습 안정성을 향상시키기 위해 bias를 사용하지 않도록 설계되었습니다.
기술 사양
- RMSNorm: bias 없이 pre-normalization으로 사용됩니다.
- Rotary Position Embeddings (RoPE): 위치 정보를 처리하기 위해 queries와 keys에 적용됩니다.
- SwiGLU Feed-Forward:
down(silu(gate(x)) * up(x))활성화 패턴을 구현합니다. - Grouped-Query Attention (GQA): 여러 query heads를 공유하는 더 작은 set의 key/value heads를 사용하여 메모리와 연산을 최적화합니다.
- Multi-Token Prediction (MTP): 다음
K개의 tokens를 예측하기 위해K개의 output heads를 채택하여, 학습된 표현력을 향상시키고 speculative decoding을 지원합니다 (단, 생성 시에는 주로 head 0을 사용합니다). - Byte-level BPE Tokenizer: GPT-2 스타일의 pretokenization을 사용하는 커스텀 구현으로, 공백이 독립적인 tokens로 낭비되지 않도록 보장합니다.
모델 구성
| Version | Dimension | Q/KV Heads | Layers | Context | Vocab | Parameters |
|---|---|---|---|---|---|---|
| Small (CPU) | 128 | 4 / 2 | 4 | 128 | 512 | ~1.05M |
| GPU Pipeline | 768 | 12 / 4 | 16 | 512 | 4096 | ~116M |
CUDA 엔진 및 성능
단일 소비자용 GPU (예: RTX 4070)에서 학습을 가능하게 하기 위해, NanoEuler는 forward 및 backward passes, 학습, 그리고 추론을 처리하는 완전한 CUDA port를 포함합니다.
커널 구현
GPU 엔진은 TF32 tensor cores를 통한 행렬 곱셈을 위해 cuBLAS를 활용합니다. 핵심적인 성능 최적화는 직접 작성한 FlashAttention 커널로, tiling과 online softmax를 사용하여 $T imes T$ 행렬을 메모리에 저장하는 것을 피합니다. 이 구현을 통해 학습 속도가 약 3배 향상되었습니다.
검증 및 안정성
직접 작성한 backpropagation은 미세한 오류가 발생하기 쉽기 때문에, NanoEuler는 엄격한 검증 프로세스를 채택합니다. 모든 analytic gradient는 부동 소수점 cancellation 효과로 인해 오류가 가려지는 것을 방지하기 위해 double precision에서 central finite difference와 비교됩니다. GPU 커널은 CPU reference와 추가로 검증되어, gradients가 $1e-6$ 이내로 일치합니다.
학습 파이프라인: Pretraining에서 SFT까지
NanoEuler는 원시 데이터에서 기능적인 (비록 규모는 작지만) chat interface까지 언어 모델의 전체 라이프사이클을 보여줍니다.
데이터 수집
이 프로젝트는 데이터 수집을 위해 Python 의존성을 피하고, shell scripts와 DuckDB CLI를 사용하여 다음을 수집합니다:
- Books: Project Gutenberg의 퍼블릭 도메인 고전 문학.
- Web: FineWeb-Edu 데이터셋의 고품질 교육용 슬라이스.
- Instructions: supervised fine-tuning을 위한 Alpaca 데이터셋.
2단계 학습 프로세스
- Pretraining: 약 116M 파라미터의 base model은 결합된 books와 web corpus로 학습됩니다. 이 단계는 모델에게 문법, register, 그리고 기본적인 언어 패턴을 가르칩니다.
- Supervised Fine-Tuning (SFT): 사전 학습된 base는 Alpaca 데이터셋을 사용하여 fine-tuning됩니다. Loss는 response tokens에 대해서만 mask 처리됩니다. 즉, 모델은 prompt와 padding을 무시하고 정답을 예측하도록 학습됩니다. 이는 모델에게 방대한 세계 지식을 위해 필요한 거대한 규모 없이도 어시스턴트의 형태 (instruction $ ightarrow$ response)를 가르칩니다.
이론적 토대: "Euler"와의 연결 고리
이 프로젝트의 이름은 residual networks와 ordinary differential equations (ODEs) 사이의 수학적 관계 때문에 Leonhard Euler의 이름을 따왔습니다.
Residual block에서 연산 $x = x + f(x)$는 수치 적분(numerical integration)을 위한 forward-Euler method를 반영합니다. 여기서 $x(t+\Delta t) = x(t) + \Delta t imes f(x(t))$입니다. $\Delta t = 1$인 경우, 깊은 residual network는 깊이가 적분 시간(integration time)을 나타내고 각 layer가 hidden state를 forward로 한 Euler step만큼 적분하는 이산화된 ODE로 볼 수 있습니다.