← Back to all spotlights

Train LLMs in Pure C: Inside Andrej Karpathy's llm.c

Andrej Karpathy's llm.c strips away gigabytes of PyTorch bloat to train GPT models in raw C and CUDA. Here is the architecture, setup, and practical code.

P24
By Pickwise24 Editorial Team
Verified Open-Source Review

What Is karpathy/llm.c?

llm.c is an open-source deep learning repository developed by Andrej Karpathy that trains and runs large language modelsβ€”specifically GPT-2 and GPT-3 style architecturesβ€”entirely in raw C and CUDA. It carries zero dependencies on Python runtime environments, PyTorch, or heavy machine learning frameworks.

  • Repository: https://github.com/karpathy/llm.c
  • Primary Language: C99 and CUDA (C++)
  • Core Function: End-to-end forward pass, backward pass, and optimiser implementation for transformer training and inference directly on raw silicon.

The Dependency Trap: Why PyTorch Needs an Antidote

Every modern AI engineer knows the ritual: you spin up a cloud box, run pip install torch, and watch your disk vanish beneath 4.5 gigabytes of pre-compiled wheels, transitive C++ runtimes, and Python wrapper layers. If your host CUDA version is even half a minor release out of sync with PyTorch’s expectations, your afternoon is effectively written off to library triage.


β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   PyTorch Training                     β”‚
β”‚  Python Interpreter β†’ PyTorch C++ API β†’ ATen/cuBLAS    β”‚
β”‚  (Gigabytes of binaries, dynamic dispatch overhead)    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           vs
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     llm.c Engine                       β”‚
β”‚  Raw C Host Code ──► Custom CUDA Kernels / cuBLASLt   β”‚
β”‚  (Single static binary, compiles in seconds)           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The AI research community on X and YouTube has spent the last year debating framework fatigue. When PyTorch abstracts away the hardware, developers stop understanding the hardware. We treat backpropagation like an incantation rather than arithmetic over pointers.

llm.c cuts straight through this abstraction sprawl. Karpathy wrote a complete training pipeline for GPT-2 in roughly 1,000 lines of clean C and CUDA. There is no interpreter spinning cycles in the background, no hidden memory allocators holding GPU VRAM hostage, and no waiting five minutes for a JIT compiler to warm up.

Architectural Breakdown: How llm.c Operates

llm.c is not a toy proof-of-concept; it is a competitive, high-throughput training harness. It achieves training speeds that rivalβ€”and occasionally exceedβ€”unoptimised PyTorch baselines by executing the mathematical operations directly against NVIDIA hardware primitives.

1. Explicit Memory Allocation: Instead of dynamic tensor allocations that fragment VRAM, llm.c computes the exact state size required for the model parameters, activations, and gradients upfront. It allocates one contiguous buffer on the GPU using cudaMalloc.

2. Hand-Crafted Forward and Backward Passes: Every layer of the transformerβ€”LayerNorm, Multi-Head Attention, GeLU activations, Residual connections, and Cross-Entropy lossβ€”features explicit C and CUDA implementations for both forward inference and reverse-mode automatic differentiation.

3. Kernel Fusion: Rather than ping-ponging data between global GPU memory and compute units across isolated operations, llm.c fuses operations (such as LayerNorm combined with residual adds) directly inside custom CUDA kernels.

4. Precision Agility: The engine supports standard FP32, mixed-precision BF16, and FP8 via NVIDIA cuBLAS and cuBLASLt libraries, ensuring Tensor Core saturation on Ada Lovelace, Hopper, and Blackwell architectures.

5. Multi-GPU Scaling: Scaling beyond a single card does not require complex Python distributed libraries. It uses standard MPI (Message Passing Interface) and NCCL (NVIDIA Collective Communications Library) to coordinate data-parallel gradients across nodes.

FeatureTypical PyTorch Pipelinekarpathy/llm.c
Disk Footprint~3 GB to 6 GB< 10 MB (source + binary)
Compilation TimeN/A (Dynamic/Prebuilt)2 to 10 seconds via nvcc
Runtime OverheadPython interpreter overheadBare-metal host execution
Memory ManagementDynamic PyTorch caching allocatorSingle static contiguous allocation
Inspection SimplicityDeep call stacks through C++/PythonSingle-step debugging in GDB/LLDB

Hands-On: Compiling and Running llm.c

To see why the system programming crowd is enamoured with this approach, clone the repository and run the reference model on your local machine.

1. Compilation

You will need a standard C compiler (gcc or clang) for the CPU-only reference, or NVIDIA's CUDA toolkit (nvcc) for the accelerated version.


# Clone the repository
git clone https://github.com/karpathy/llm.c.git
cd llm.c

# Compile the high-performance CUDA training binary
make train_gpt2cu

The build completes in a handful of seconds. You are left with a single, standalone binary: train_gpt2cu.

2. Tokenisation and Data Ingestion

Before training, you need tokens. The repository includes clean utilities to download the FineWeb or TinyStories datasets and tokenize them into compact binary shards:


# Install minimal requirements strictly for initial data prep
pip install tiktoken requests

# Download and tokenize a small sample of FineWeb
python dev/data/tinyshakespere.py

This generates data/tinyshakespeare_train.binβ€”raw token integers laid out sequentially on disk.

3. Training the Model

Launch training directly from your terminal:


# Run the training binary on your GPU
./train_gpt2cu \
    -i "data/tinyshakespeare_train.bin" \
    -v "data/tinyshakespeare_val.bin" \
    -b 4 \
    -s 1024 \
    -l 0.0001 \
    -m 1000

There are no warnings about deprecation, no thread contention from Python's Global Interpreter Lock (GIL), and no mystery background processes. The terminal outputs step counts, token processing velocities, and cross-entropy loss metrics calculated directly by your GPU's streaming multiprocessors.


Why llm.c Matters to AI Builders

For years, the industry assumption has been that low-level C and CUDA are too brittle for fast-paced machine learning development. llm.c dismantles that premise. By isolating the canonical GPT architecture, Karpathy has created the ultimate educational and production reference.

If you are embedding LLM training directly into robotics runtimes, micro-appliances, or proprietary edge hardware where a Python runtime is a liability, llm.c provides the blueprint. It proves that behind the mystique of contemporary artificial intelligence sits deterministic, inspectable, and remarkably elegant systems software.

Key Takeaways

  • Zero Framework Bloat: Eliminates Python, PyTorch, and third-party runtime dependencies in favour of raw C99 and CUDA.
  • Deterministic Resource Consumption: Allocates GPU memory statically up front, eliminating out-of-memory surprises caused by dynamic allocation caches.
  • Pure Reference Architecture: Provides an unvarnished view of transformer forward and backward mathematical passes without abstraction layers.

πŸ›‘οΈ Editorial Standards & Methodology

Every repository featured on Pickwise24 undergoes testing on local workstation hardware before publication. We verify CLI installation steps, review open-source repository licensing, benchmark computational footprint, and evaluate architectural trade-offs to provide genuine, high-utility developer intelligence.