CUDAlab 是一个用于学习和实验的大模型推理框架。项目用 C++17 和 CUDA 实现了模型加载、Tokenizer、Tensor、基础算子、KV Cache、Paged Attention、连续批处理调度等模块,当前主要支持 Llama/Llama3、Qwen2.5 和 Qwen3 系列模型的本地推理。
这个仓库适合用来理解一个轻量 LLM inference runtime 从模型权重到 token 输出的完整链路,而不是直接替代生产级推理服务。
- C++17/CUDA 推理核心
- CPU 和 CUDA 双后端算子
- Llama/Llama3、Qwen2.5、Qwen3 模型结构支持
- SentencePiece、BPE/TikToken 风格 tokenizer 支持
- FP32/FP16 权重导出入口
- 普通自回归推理 demo
- Paged KV Cache 和 Paged Attention
- 简单 continuous batching 调度器
- Paged Attention、KV Cache、Scheduler 等单元测试
- Paged Attention 和 batch inference benchmark demo
.
├── cmake/ # CMake/CPM/CUDA 配置
├── demo/ # 推理、批处理和 benchmark 示例
├── hf_infer/ # HuggingFace 对照推理脚本
├── kuiper/
│ ├── include/ # 公开头文件
│ └── source/ # Runtime、模型、算子、调度器实现
├── models/ # 本地模型文件目录,可自行放置 bin/tokenizer
├── test/ # GTest 单元测试
├── tools/ # HuggingFace/Meta 权重导出脚本
└── readme.md
核心模块:
kuiper/source/model: Llama、Qwen 模型前向流程kuiper/source/op: embedding、matmul、rmsnorm、rope、mha、swiglu 等算子封装kuiper/source/op/kernels: CPU/CUDA kernel 实现和后端分发kuiper/source/paged_attention: Paged Attention 入口kuiper/source/kv_cache: 分页 KV Cache 的 block table 和 block managerkuiper/source/scheduler: 简单请求调度器demo/batch_infer.cpp: 基于 scheduler 和 paged KV cache 的批量推理示例
基础依赖:
- CMake 3.16+
- C++17 编译器
- CUDA Toolkit
- glog
- GTest
- sentencepiece
- Armadillo
启用 Llama3/Qwen2/Qwen3 时还需要:
- abseil-cpp
- re2
- nlohmann_json
Python 导出脚本通常还需要:
- Python 3
- torch
- transformers
- numpy
- sentencepiece
- huggingface_hub 或 huggingface-cli
默认编译基础库、测试和 demo:
mkdir -p build
cd build
cmake ..
make -j16如果希望用 CPM 自动拉取部分 C++ 依赖:
mkdir -p build
cd build
cmake -DUSE_CPM=ON ..
make -j16启用特定模型族支持:
# Llama3 / Llama3.2
cmake -DUSE_CPM=ON -DLLAMA3_SUPPORT=ON ..
# Qwen2.5
cmake -DUSE_CPM=ON -DQWEN2_SUPPORT=ON ..
# Qwen3
cmake -DUSE_CPM=ON -DQWEN3_SUPPORT=ON ..构建产物一般位于:
build/demo/llama_infer
build/demo/batch_infer
build/demo/bench_paged_attention
build/test/test_llm
lib/libllama.so
如果你使用仓库里已有的 build-mini-vllm 目录,命令路径相应替换为 build-mini-vllm/demo/... 即可。
项目推理程序读取自定义 .bin 权重格式。可以使用 tools/ 下脚本从 HuggingFace 或 Meta 权重导出。
python3 tools/export_llama.py models/llama.bin --hf=/path/to/hf-llama --dtype=fp32也可以使用 Meta 原始权重目录:
python3 tools/export_llama.py models/llama.bin --meta-llama=/path/to/meta/llamapython3 tools/export_llama3.py models/llama3.bin --hf=/path/to/Llama-3.x --dtype=fp32示例下载:
export HF_ENDPOINT=https://hf-mirror.com
huggingface-cli download --resume-download meta-llama/Llama-3.2-1B \
--local-dir models/Llama-3.2-1B \
--local-dir-use-symlinks False
python3 tools/export_llama3.py models/llama3_1b.bin --hf=models/Llama-3.2-1Bhuggingface-cli download --resume-download Qwen/Qwen2.5-0.5B \
--local-dir models/Qwen2.5-0.5B \
--local-dir-use-symlinks False
python3 tools/export_qwen2.py models/qwen2_0.5b.bin --hf=models/Qwen2.5-0.5BQwen3 目前走两步导出:
python3 tools/export_qwen3/load.py \
--model_name /path/to/Qwen3 \
--output_file models/qwen3_weights.pth
python3 tools/export_qwen3/write_bin.py \
--checkpoint models/qwen3_weights.pth \
--model_name /path/to/Qwen3 \
--device cpuwrite_bin.py 默认输出 qwen0.6.bin。如果需要自定义输出文件名,可以在脚本中修改 file_path。
编译时启用对应选项后运行:
./build/demo/llama_infer models/llama3_1b.bin models/Llama-3.2-1B/tokenizer.json如果是 SentencePiece tokenizer:
./build/demo/llama_infer models/llama.bin models/tokenizer.model./build/demo/qwen_infer models/qwen2_0.5b.bin models/Qwen2.5-0.5B/tokenizer.json./build/demo/qwen3_infer models/qwen0.6.bin /path/to/Qwen3/tokenizer.jsondemo/batch_infer.cpp 展示了一个简单的 continuous batching 流程:
./build/demo/batch_infer models/llama3_1b.bin models/Llama-3.2-1B/tokenizer.json \
--request_num=8 \
--max_batch_size=4 \
--max_new_tokens=64 \
--block_size=16 \
--prompt=hello \
--print=0参数说明:
request_num: 总请求数max_batch_size: 每轮最多处理的请求数max_new_tokens: 每个请求最多生成 token 数block_size: Paged KV Cache 每个 block 容纳的 token 数prompt: 所有请求共用的输入 promptprint: 是否打印每个请求的输出,1打印,0不打印
输出为 CSV 风格指标,包括生成 token 数、总耗时、吞吐、请求吞吐、平均延迟和 p95 延迟。
Paged Attention 和 Scheduler benchmark:
./build/demo/bench_paged_attention \
--seq_len=512 \
--head_num=8 \
--head_size=64 \
--kv_mul=1 \
--block_size=16 \
--repeat=100 \
--request_num=64 \
--max_batch_size=8 \
--prompt_len=32 \
--max_new_tokens=64该程序会对比:
- CPU contiguous MHA
- CPU paged MHA
- CUDA contiguous MHA
- CUDA paged MHA
- sequential scheduler
- continuous scheduler
编译后运行:
./build/test/test_llm测试覆盖包括:
- Tensor 和 Buffer
- CUDA 基础算子
- 模型加载和部分模型推理流程
- Scheduler
- KV Cache BlockManager
- Paged Attention CPU/CUDA 对照
paged_attention::forward 是 Paged Attention 的统一入口:
kuiper/source/model/llama3.cpp
-> paged_attention::forward
-> kernel::get_paged_mha_kernel(device_type)
-> CPU: kuiper/source/op/kernels/cpu/mha_kernel.cpp::paged_mha_kernel
-> CUDA: kuiper/source/op/kernels/cuda/mha_kernel.cu::paged_mha_kernel_cu
相关文件:
kuiper/include/paged_attention/paged_attention.hkuiper/source/paged_attention/paged_attention.cppkuiper/source/op/kernels/kernels_interfaces.cppkuiper/source/op/kernels/cpu/mha_kernel.cppkuiper/source/op/kernels/cuda/mha_kernel.cu
根 CMakeLists.txt 中默认写了:
set(CMAKE_CUDA_COMPILER "/usr/local/cuda/bin/nvcc")如果 CUDA 安装在其他路径,需要修改这里或通过 CMake 参数指定 CUDA 编译器。
这些依赖只在启用 LLAMA3_SUPPORT、QWEN2_SUPPORT 或 QWEN3_SUPPORT 时需要。可以用:
cmake -DUSE_CPM=ON -DLLAMA3_SUPPORT=ON ..让 CPM 尝试自动下载依赖;如果网络不可用,需要提前在系统环境中安装对应库。
- Llama/Llama2 通常使用
tokenizer.model - Llama3、Qwen2.5、Qwen3 通常使用 HuggingFace 模型目录下的
tokenizer.json
具体取决于 demo 中创建模型时选择的 TokenizerType。
可以在项目根目录运行可执行文件,或手动设置:
export LD_LIBRARY_PATH=$PWD/lib:$LD_LIBRARY_PATH本项目来自 KuiperInfer/KuiperLLama 系列学习项目,目标是用尽量清晰的代码展示大模型推理框架的关键组成部分:模型权重读取、Tokenizer、算子、CUDA 后端、KV Cache、Paged Attention 和批处理调度。