DeepGEMM 构建系统与基础设施架构分析
本文档深入分析 DeepGEMM 项目的构建管线(Build Pipeline)、第三方集成、测试框架与 CI/CD 基础设施,面向 AI 系统与芯片研究人员,旨在揭示其工程架构设计决策与演进脉络。
目录
- 1. 项目概览与设计哲学
- 2. 构建管线总览
- 3. setup.py 深度剖析
- 4. 构建脚本对比:installsh vs developsh vs buildsh
- 5. CMakeLists.txt 的角色
- 6. JIT vs AOT 编译策略
- 7. 第三方库集成
- 8. 环境变量体系
- 9. 代码生成:.pyi Stub 生成
- 10. 测试架构
- 11. CI/CD 基础设施
- 12. 项目演进时间线
- 13. 关键工程洞察
1. 项目概览与设计哲学
DeepGEMM 是一个统一的高性能 Tensor Core 内核库,将现代 LLM 的关键计算原语(FP8/FP4/BF16 GEMM、融合 MoE、MQA scoring、HyperConnection)整合到单一 CUDA 代码库中。其核心设计哲学是:
"All kernels are compiled at runtime via a lightweight Just-In-Time (JIT) module, requiring no CUDA compilation during installation."
这意味着:
- 安装阶段不编译 CUDA(仅编译轻量 C++ JIT 宿主模块)
- 运行时按需 JIT 编译具体 kernel 到 SASS
- 用户下载的 wheel 不含任何 .cubin,极大简化分发
2. 构建管线总览
2.1 端到端构建流程图
flowchart TD
A[git clone --recursive] --> B[./install.sh]
B --> C[python setup.py bdist_wheel]
C --> D{CachedWheelsCommand}
D -->|DG_FORCE_BUILD=1 或 local version| E[本地构建]
D -->|默认发布模式| F[尝试下载预编译 wheel]
F -->|下载成功| G[直接重命名放置到 dist/]
F -->|下载失败| E
E --> H[CustomBuildPy.run]
H --> H1[prepare_includes: 复制 CuTe/cutlass 头文件到 build 目录]
H1 --> H2[generate_default_envs: 生成 envs.py]
H2 --> H3[generate_pyi_file: 从 C++ 生成 _C.pyi 类型桩]
H3 --> H4[标准 build_py + CUDAExtension 编译]
H4 --> I[生成 deep_gemm-<ver>+cu<cu>-torch<torch>-cxx11abi<abi>-<py>-<platform>.whl]
I --> J[pip install dist/*.whl --force-reinstall]
2.2 构建产物结构
deep_gemm-<version>+cu<cuda>-torch<torch>-cxx11abi<abi>-cp<py>-linux_x86_64.whl
└── deep_gemm/
├── __init__.py # 入口,调用 _C.init()
├── _C.so # 轻量 JIT 宿主(不含 kernel 代码)
├── _C.pyi # 自动生成的类型桩
├── envs.py # 构建时捕获的环境变量默认值
├── include/
│ ├── deep_gemm/**/* # 真实 kernel 头文件(JIT 编译时 include)
│ ├── cute/**/* # CUTLASS CuTe 子集
│ └── cutlass/**/* # CUTLASS 子集
├── utils/ # Python 工具函数
├── testing/ # 测试基础设施
├── legacy/ # Triton 遗留内核(A100)
└── mega/ # Mega MoE 对称内存管理
3. setup.py 深度剖析
setup.py 是整个构建系统的核心,继承了 setuptools 的多个命令类进行定制。
3.1 全局配置与编译器标志
cxx_flags = ['-std=c++17', '-O3', '-fPIC', '-Wno-psabi', '-Wno-deprecated-declarations',
f'-D_GLIBCXX_USE_CXX11_ABI={int(torch.compiled_with_cxx11_abi())}']
关键设计点:
- C++17 用于构建宿主模块(JIT 编译器等),但 kernel 本身使用 C++20(通过 DG_JIT_CPP_STANDARD 控制)
- _GLIBCXX_USE_CXX11_ABI 与 PyTorch 保持一致,避免 ABI 不匹配导致的 undefined symbol 错误
- DG_JIT_USE_RUNTIME_API 可选启用 CUDA Runtime API 加载 kernel(需 CUDA >= 12.8)
3.2 源文件与依赖配置
sources = ['csrc/python_api.cpp'] # 单一入口文件
build_include_dirs = [
f'{CUDA_HOME}/include',
f'{CUDA_HOME}/include/cccl', # CUDA Core Compute Libraries
'deep_gemm/include', # 项目自身头文件
'third-party/cutlass/include', # CUTLASS
'third-party/fmt/include', # fmt 格式化库
]
build_libraries = ['cudart', 'nvrtc'] # CUDA Runtime + NVRTC
注意:CUDA_HOME 来自 torch.utils.cpp_extension.CUDA_HOME,即与 PyTorch 编译时一致的 CUDA 版本。
3.3 版本管理系统
def get_package_version():
# 从 deep_gemm/__init__.py 读取公开版本号
public_version = ast.literal_eval(version_match.group(1)) # 如 '2.4.2'
revision = ''
if DG_USE_LOCAL_VERSION:
# 检查 git 工作区是否干净
# 干净: +<short_sha> 不干净: assert 失败
revision = '+' + subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'])
return f'{public_version}{revision}'
版本策略:
- 发布模式(DG_USE_LOCAL_VERSION=0):纯版本号 2.4.2,用于 PyPI 发布
- 本地模式(DG_USE_LOCAL_VERSION=1,默认):2.4.2+abc1234,要求 git 干净
3.4 CustomBuildPy — 自定义构建流程
class CustomBuildPy(build_py):
def run(self):
self.prepare_includes() # 1. 准备头文件
self.generate_default_envs() # 2. 生成 envs.py
self.generate_pyi_file() # 3. 生成 .pyi 类型桩
build_py.run(self) # 4. 标准构建
prepare_includes()
def prepare_includes(self):
build_include_dir = os.path.join(self.build_lib, 'deep_gemm/include')
for d in third_party_include_dirs: # ['third-party/cutlass/include/cute', '.../cutlass']
shutil.copytree(src_dir, dst_dir) # 复制到 build 目录
设计决策:不修改源目录,所有第三方头文件复制到 build_lib/deep_gemm/include/ 下,保持源目录干净。
generate_default_envs()
def generate_default_envs(self):
code = '# Pre-installed environment variables\n'
code += 'persistent_envs = dict()\n'
for name in ('DG_JIT_CACHE_DIR', 'DG_JIT_PRINT_COMPILER_COMMAND', 'DG_JIT_CPP_STANDARD'):
code += f"persistent_envs['{name}'] = '{os.environ[name]}'\n" if name in os.environ else ''
作用:将构建时的关键环境变量"冻结"到 envs.py,运行时 __init__.py 会自动恢复这些默认值。
generate_pyi_file()
调用 scripts/generate_pyi.py 从 C++ 源码提取函数签名,生成 _C.pyi 类型桩,详见第 9 节。
3.5 CachedWheelsCommand — 智能 Wheel 下载
class CachedWheelsCommand(_bdist_wheel):
def run(self):
if DG_FORCE_BUILD or DG_USE_LOCAL_VERSION:
return super().run() # 强制本地构建
wheel_url, wheel_filename = get_wheel_url()
try:
# 尝试从 GitHub Release 下载(1 秒超时)
urllib.request.urlopen(wheel_url, timeout=1)
# 下载成功:直接重命名为 wheel 格式
except (HTTPError, URLError):
# 下载失败:回退到本地源码构建
super().run()
Wheel URL 构造
def get_wheel_url():
wheel_filename = (
f'deep_gemm-{deep_gemm_version}+cu{cuda_version}'
f'-torch{torch_version}-cxx11abi{cxx11_abi}'
f'-{python_version}-{platform_name}.whl'
)
# 示例: deep_gemm-2.4.2+cu129-torch2.8-cxx11abi0-cp312-linux_x86_64.whl
wheel_url = f'https://github.com/DeepSeek-AI/DeepGEMM/releases/download/v{version}/{wheel_filename}'
关键决策:
- 使用 PyTorch 编译时的 CUDA 版本(torch.version.cuda),而非系统当前安装的 CUDA
- 区分 cxx11_abi 是因为 PyTorch 官方 wheel 未启用 C++11 ABI,但 NVIDIA 容器镜像(nvcr)中的 PyTorch 启用了
3.6 get_ext_modules — 条件性 CUDA 扩展
def get_ext_modules():
if DG_SKIP_CUDA_BUILD:
return [] # 跳过 CUDA 构建(用于 PyPI 纯 Python 发布)
return [CUDAExtension(name='deep_gemm._C', ...)]
4. 构建脚本对比:install.sh vs develop.sh vs build.sh
flowchart LR
subgraph install.sh
I1[rm -rf build dist] --> I2[python setup.py bdist_wheel]
I2 --> I3[pip install dist/*.whl --force-reinstall]
end
subgraph develop.sh
D1[ln -sf cutlass 头文件到 deep_gemm/include] --> D2[rm -rf build dist]
D2 --> D3[python setup.py build]
D3 --> D4[find .so 创建符号链接到 deep_gemm/]
end
subgraph build.sh
B1[rm -rf build dist] --> B2[python setup.py bdist_wheel]
end
| 脚本 | 主要用途 | 产物 | 特点 |
|---|---|---|---|
install.sh |
生产部署 | .whl 安装到 site-packages |
完整安装流程 |
develop.sh |
开发调试 | build/ 目录 + 符号链接 |
不创建 wheel,直接链接 .so |
build.sh |
CI/CD 构建 | .whl 文件 |
仅构建不安装 |
develop.sh 的特殊处理
# 创建符号链接,让 Python 能找到头文件
ln -sf $script_dir/third-party/cutlass/include/cutlass deep_gemm/include
ln -sf $script_dir/third-party/cutlass/include/cute deep_gemm/include
# 构建后创建 .so 符号链接
so_file=$(find build -name "*.so" -type f | head -n 1)
ln -sf "../$so_file" deep_gemm/
注意:这些符号链接被 .gitignore 忽略(deep_gemm/include/cute、deep_gemm/include/cutlass、deep_gemm/*.so),不会进入 git 历史。
5. CMakeLists.txt 的角色
# NOTES: current just for CMake-based IDE (e.g. CLion) indexing, the real compilation is done via JIT
cmake_minimum_required(VERSION 3.10)
project(deep_gemm LANGUAGES CXX CUDA)
5.1 仅用于 IDE 索引
CMakeLists.txt 不参与实际编译,仅为 CLion 等 CMake-based IDE 提供代码索引:
# C++20/CUDA20 标准(与 kernel JIT 编译一致)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CUDA_STANDARD 20)
# 主 Python API 入口(IDE 索引用)
pybind11_add_module(_C csrc/python_api.cpp)
# 关键:所有 kernel 头文件都 include 进来供索引
cuda_add_library(deep_gemm_indexing_cuda STATIC csrc/indexing/main.cu)
5.2 csrc/indexing/main.cu — 索引专用文件
// GEMM kernels
#include <deep_gemm/impls/sm90_bf16_gemm.cuh>
#include <deep_gemm/impls/sm90_fp8_gemm_1d1d.cuh>
// ... 所有 kernel 头文件
int main() { return 0; } // 空 main,仅用于编译索引
设计意图:让 IDE 能解析所有 kernel 定义的符号,提供代码补全和跳转,但不生成任何可执行代码。
5.3 与真实 JIT 构建的差异
| 特性 | CMakeLists.txt | 真实 JIT 构建 |
|---|---|---|
| 目的 | IDE 索引 | 运行时 kernel 编译 |
| 编译目标 | 无(仅索引) | .cubin 文件 |
| 编译器 | CMake 调用 nvcc | Compiler 类直接调用 nvcc |
| 输出 | 无 | ~/.deep_gemm/<hash>/kernel.cubin |
| CUDA 架构 | CUDA_ARCH_LIST 变量 |
运行时自动检测 |
6. JIT vs AOT 编译策略
6.1 设计决策:全 JIT 编译
DeepGEMM 的核心创新是完全不使用 AOT(Ahead-Of-Time)编译 CUDA kernel:
传统 CUTLASS 流程:
setup.py → nvcc 编译所有 SM arch → 链接巨大 .so → 分发 GB 级 wheel
DeepGEMM 流程:
setup.py → 仅编译轻量 _C.so(< 1MB) → 分发 wheel
运行时 → 首次调用 kernel → JIT 编译为 .cubin → 缓存到 ~/.deep_gemm/
6.2 JIT 编译流程
flowchart TD
A[Python 调用 deep_gemm.fp8_gemm_nt] --> B[_C.so 中的 pybind11 绑定]
B --> C[JIT Compiler: 解析 #include <deep_gemm/...>]
C --> D[递归展开所有头文件依赖]
D --> E[计算依赖哈希值]
E --> F{缓存命中?}
F -->|命中| G[加载 ~/.deep_gemm/<hash>/kernel.cubin]
F -->|未命中| H[nvcc 编译为 .cubin]
H --> I[缓存到磁盘]
I --> G
G --> J[cuModuleLoadData 加载 cubin]
J --> K[cuLaunchKernel 执行]
6.3 关键组件
- IncludeParser:递归解析
#include <deep_gemm/*>指令,构建完整编译单元 - KernelRuntimeCache:内存中的 cubin 运行时缓存
- 磁盘缓存:
~/.deep_gemm/<hash>/目录,跨进程共享编译结果 - NVRTC 支持:可选使用
DG_JIT_USE_NVRTC=1启用,编译速度提升 10x 但可能有性能损失
6.4 为什么选择 JIT
- 分发体积小:wheel 仅 ~1MB,而非数百 MB 的 cubin 集合
- 架构适配:运行时检测 GPU 架构,只编译需要的 kernel
- 迭代速度:修改 kernel 代码无需重新安装,删除缓存即可
- 实验灵活:支持
set_ignore_compile_dims、set_block_size_multiple_of等运行时调优
7. 第三方库集成
7.1 子模块管理
[submodule "third-party/cutlass"]
path = third-party/cutlass
url = https://github.com/NVIDIA/cutlass.git
[submodule "third-party/fmt"]
path = third-party/fmt
url = https://github.com/fmtlib/fmt.git
注意:tilelang_ops 不是 git 子模块,而是直接包含在仓库中的代码。
7.2 CUTLASS — 核心依赖
DeepGEMM 使用 CUTLASS 4.0+ 的两个子集:
| 组件 | 用途 | 安装方式 |
|---|---|---|
CuTe (cute/) |
Tensor 布局、拷贝原语、TMA 抽象 | 复制到 deep_gemm/include/cute/ |
CUTLASS (cutlass/) |
MMA 描述、架构特性 | 复制到 deep_gemm/include/cutlass/ |
关键区别:DeepGEMM 不使用 CUTLASS 的:
- 高层 GEMM 调度器(device/gemm/)
- 复杂的 epilogue 框架
- C++ 模板元编程代数
"DeepGEMM leverages some concepts from CUTLASS and CuTe, but avoids heavy reliance on their templates or algebras."
7.3 fmt — 格式化库
// 使用 fmt 进行编译时字符串格式化
flags = fmt::format("-std=c++{} --diag-suppress=39,161,...",
get_env<int>("DG_JIT_CPP_STANDARD", 20));
用途:
- JIT 编译命令字符串格式化
- 日志输出
- 错误信息构建
7.4 tilelang_ops — Mega MoE 基线
# tests/test_mega_moe.py
spec = importlib.util.spec_from_file_location(
'tilelang_ops',
os.path.join('..', 'third-party', 'tilelang_ops', '__init__.py'))
tilelang_ops = importlib.util.module_from_spec(spec)
仅用于测试:
- 提供 swiglu_apply_weight_to_fp8 函数
- 作为 Mega MoE 正确性验证的非融合基线
- 不是主构建依赖,加载失败仅跳过基线 benchmark
7.5 子模块状态
git submodule status:
-f3fde58... third-party/cutlass (- 表示未初始化)
-553ec11...... third-party/fmt (- 表示未初始化)
用户必须执行 git submodule update --init 才能获取这些依赖。
8. 环境变量体系
8.1 完整 DG_* 变量清单
| 变量 | 默认值 | 用途 | 影响范围 |
|---|---|---|---|
DG_JIT_DEBUG |
0 |
打印 JIT 调试信息 | 编译阶段 |
DG_PRINT_CONFIGS |
0 |
打印每个 shape 选择的配置 | 运行时 |
DG_JIT_CACHE_DIR |
$HOME/.deep_gemm |
编译缓存目录 | 磁盘缓存 |
DG_JIT_USE_NVRTC |
0 |
使用 NVRTC 替代 NVCC | 编译器选择 |
DG_JIT_NVCC_COMPILER |
CUDA_HOME/nvcc |
NVCC 路径 | 编译器选择 |
DG_JIT_CPP_STANDARD |
20 |
C++ 标准版本 | 编译器选择 |
DG_JIT_PRINT_COMPILER_COMMAND |
0 |
打印编译命令 | 编译器输出 |
DG_JIT_PTXAS_VERBOSE |
0 |
详细 PTXAS 输出 | 编译器输出 |
DG_JIT_PTXAS_CHECK |
0 |
检查 local memory 使用 | 编译器输出 |
DG_JIT_PRINT_LOAD_TIME |
0 |
打印 kernel 加载时间 | 编译器输出 |
DG_JIT_WITH_LINEINFO |
0 |
嵌入源码行信息 | 调试分析 |
DG_JIT_DUMP_ASM |
0 |
转储 PTX 和 SASS | 调试分析 |
DG_JIT_DUMP_PTX |
0 |
转储 PTX | 调试分析 |
DG_JIT_DUMP_SASS |
0 |
转储 SASS | 调试分析 |
DG_COMM_KERNEL_DEBUG |
0 |
Mega MoE 调试模式(zero buffer) | 内核调试 |
DG_USE_NVIDIA_TOOLS |
0 |
跳过内部 profiling(配合 Nsight) | 性能分析 |
DG_SKIP_CUDA_BUILD |
0 |
跳过 CUDA 扩展构建 | 构建选项 |
DG_FORCE_BUILD |
0 |
强制本地构建 | 构建选项 |
DG_USE_LOCAL_VERSION |
1 |
使用本地版本号 | 构建选项 |
DG_JIT_USE_RUNTIME_API |
0 |
使用 CUDA Runtime API 加载 | 构建选项 |
8.2 运行时持久化机制
构建时捕获的环境变量会被"冻结"到 envs.py:
# deep_gemm/envs.py (自动生成)
persistent_envs = dict()
persistent_envs['DG_JIT_CACHE_DIR'] = '/home/user/.deep_gemm'
# ... 仅包含构建时存在的变量
运行时恢复:
# deep_gemm/__init__.py
from .envs import persistent_envs
for key, value in persistent_envs.items():
if key not in os.environ: # 不覆盖用户显式设置
os.environ[key] = value
9. 代码生成:.pyi Stub 生成
9.1 生成流程
flowchart TD
A[scripts/generate_pyi.py] --> B[build_cpp_function_index]
B --> B1[扫描 csrc/ 下所有 .cpp/.h 文件]
B1 --> B2[正则匹配函数签名]
B2 --> B3[过滤非函数关键字 if/for/return]
B3 --> B4[构建 func_name → signature 索引]
A --> C[extract_m_def_statements]
C --> C1[扫描 m.def(...)]
C --> C2[BracketTracker 解析嵌套括号]
C --> C3[提取 python_name, cpp_name, py::arg]
A --> D[parse_mdef_and_attach_cpp_signatures]
D --> D1[匹配 m.def 与 C++ 函数]
D --> D2[提取返回值类型、参数列表]
A --> E[cpp_type_to_python_type]
E --> E1[std::vector<T> → list[T]]
E --> E2[std::optional<T> → Optional[T]]
E --> E3[torch::Tensor → torch.Tensor]
E --> E4[bool/int/float/str 映射]
A --> F[generate_pyi_file_content]
F --> G[stubs/_C.pyi]
9.2 BracketTracker — 嵌套括号追踪
class BracketTracker:
def __init__(self):
self.paren = 0 # ()
self.bracket = 0 # []
self.brace = 0 # {}
self.angle = 0 # <> (仅顶层)
关键:正确处理模板参数中的逗号,如 std::tuple<int, int>({128, 128})。
9.3 类型映射表
| C++ 类型 | Python 类型 |
|---|---|
void |
None |
std::vector<T> |
list[T] |
std::optional<T> |
Optional[T] |
std::pair<T1, T2> |
tuple[T1, T2] |
std::tuple<...> |
tuple[...] |
std::string / char* |
str |
bool |
bool |
int / size_t / int64_t |
int |
float / double |
float |
torch::Tensor |
torch.Tensor |
| 其他 | Any |
9.4 默认值转换
def cpp_default_to_python_default(cpp_default: str):
if s == 'false': return 'False'
if s == 'true': return 'True'
if s in ('nullptr', 'NULL'): return 'None'
# std::tuple<int, int>({128, 128}) → (128, 128)
# std::vector<int>({1,2,3}) → [1, 2, 3]
10. 测试架构
10.1 测试文件组织
| 文件 | 覆盖范围 | kernel 类型 |
|---|---|---|
test_fp8_fp4.py |
核心 GEMM 测试 | FP8/FP4 普通、M-grouped、K-grouped |
test_bf16.py |
BF16 GEMM | BF16 普通、M-grouped、K-grouped、cuBLASLt |
test_attention.py |
MQA Logits | FP8/FP4 MQA、Paged MQA、skip head mid |
test_einsum.py |
Einsum 内核 | BF16/FP8 einsum 变体 |
test_hyperconnection.py |
HyperConnection | TF32 HC prenorm GEMM |
test_layout.py |
SF 布局内核 | TMA-aligned transpose、UE8M0 packing |
test_mega_moe.py |
Mega MoE | 融合 EP dispatch + GEMM + SwiGLU |
test_legacy.py |
Triton 遗留内核 | A100 Triton M-grouped、K-grouped |
test_lazy_init.py |
延迟初始化 | 多进程 CUDA 初始化 |
test_sanitizer.py |
内存安全检查 | compute-sanitizer 封装 |
generators.py |
测试数据生成 | 所有枚举器与生成器 |
10.2 测试模式
数据生成器模式
# generators.py 提供枚举器 + 生成器分离的设计
def enumerate_normal(dtype):
"""枚举所有测试参数组合"""
for kernel_type in get_kernel_types(dtype):
for quant_config in QuantConfig.get_list_from_dtype(dtype):
for m in m_fwd_list:
for n, k in nk_list:
yield kernel_type, quant_config, m, n, k, ...
def generate_normal(m, n, k, ...):
"""生成具体的测试张量"""
a = torch.randn((m, k), dtype=torch.bfloat16)
b = torch.randn((n, k), dtype=torch.bfloat16)
# FP8/FP4 量化
a = cast_fp8_fp4_with_major(a, ...)
return a, b, c, d, ref_d
数值验证模式
# deep_gemm/testing/numeric.py
def calc_diff(x: torch.Tensor, y: torch.Tensor):
"""余弦相似度: 1 - 2*x·y/(|x|²+|y|²)"""
x, y = x.double(), y.double()
denominator = (x * x + y * y).sum()
sim = 2 * (x * y).sum() / denominator
return 1 - sim
# 容差标准
quant_config.max_diff() # FP4: 0.02, FP4×FP8: 0.01, FP8: 0.001
性能 Benchmark 模式
# deep_gemm/testing/bench.py
def bench_kineto(fn, kernel_names, num_tests=30, ...):
"""使用 torch.profiler + Kineto 进行 GPU 内核计时"""
# 1. L2 cache flush (8 GB memset)
# 2. warmup + active profiling
# 3. 解析 profiler 表格提取内核时间
特点:
- 默认 30 次测试取平均
- 8 GB L2 cache flush 确保冷缓存基准
- 支持多内核同时计时(返回 tuple)
- 自动跳过当 DG_USE_NVIDIA_TOOLS=1(配合外部 profiling 工具)
10.3 架构条件测试
# tests/test_layout.py
@test_filter(lambda: get_arch_major() >= 10)
def test_fp8_bhd_hdr_bhr():
"""仅在 SM100+ 上运行"""
# generators.py
def get_kernel_types(dtype):
if dtype == torch.bfloat16:
return (KernelType.KernelNoSF, )
return (KernelType.Kernel1D2D, ) if get_arch_major() == 9 else (KernelType.Kernel1D1D, )
10.4 测试辅助基础设施
| 组件 | 用途 |
|---|---|
test_filter |
条件性跳过测试(基于架构) |
ignore_env |
临时忽略环境变量 |
bench |
CPU 端计时(L2 flush + 多次平均) |
bench_kineto |
GPU 端 Kineto profiling |
calc_diff |
数值差异计算 |
count_bytes |
张量字节数统计 |
get_arch_major |
获取 GPU 架构版本 |
11. CI/CD 基础设施
11.1 GitHub Actions 工作流
flowchart TD
A[触发: tag v* 创建] --> B[setup_release]
B --> B1[提取版本号]
B --> B2[创建 GitHub Release]
B --> C[build_wheels 矩阵构建]
C --> C1[_build.yml: ubuntu-22.04]
C1 --> C2[Python 3.8-3.13]
C2 --> C3[PyTorch 2.4.0-2.8.0]
C3 --> C4[CUDA 12.9.1]
C4 --> C5[cxx11_abi: FALSE/TRUE]
C5 --> D[构建 wheel]
D --> E[上传到 GitHub Release]
E --> F[publish_package]
F --> F1[安装 CPU-only PyTorch]
F --> F2[DG_SKIP_CUDA_BUILD=1 构建 sdist]
F --> F3[twine upload 到 PyPI]
11.2 构建矩阵
matrix:
os: [ubuntu-22.04]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
torch-version: ["2.4.0", "2.5.1", "2.6.0", "2.7.1", "2.8.0"]
cuda-version: ["12.9.1"]
cxx11_abi: ["FALSE", "TRUE"]
exclude:
- torch-version: "2.4.0"
python-version: "3.13" # PyTorch < 2.5 不支持 Python 3.13
理论组合数:5 Python × 5 PyTorch × 2 ABI - 1 exclude = 49 种配置
11.3 关键 CI 配置
磁盘空间管理
- name: Free up disk space
run: |
sudo rm -rf /usr/share/dotnet
sudo rm -rf /opt/ghc
sudo rm -rf /opt/hostedtoolcache/CodeQL
- name: Set up swap space
uses: pierotofy/set-swap-space@v1.0
with:
swap-size-gb: 10
构建缓存
- name: Restore build cache
uses: actions/cache/restore@v4
with:
path: build.tar
key: build-${{ inputs.release-version }}-${{ inputs.python-version }}-${{ inputs.cuda-version }}-${{ inputs.torch-version }}-${{ inputs.cxx11_abi }}-${{ github.run_number }}-${{ github.run_attempt }}
缓存策略:
- 将整个构建目录打包为 build.tar
- 超时(exit code 124)时保存缓存,下次继续
- 5 小时超时(GitHub 允许最大 6 小时)
并行控制
export MAX_JOBS=$([ "$MATRIX_CUDA_VERSION" == "129" ] && echo 1 || echo 2)
export NVCC_THREADS=2
原因:CUDA 12.9 的 nvcc 在 2 个并行 job 时会 OOM。
CUDA 架构列表
export TORCH_CUDA_ARCH_LIST="7.0 7.2 7.5 8.0 8.6 8.7 9.0+PTX"
注意:虽然 DeepGEMM 仅支持 SM90/SM100,但 CI 构建的 _C.so 包含更广泛的架构兼容性(可能用于未来扩展)。
11.4 手动触发工作流
build.yml 支持 workflow_dispatch 手动触发,可自定义:
- runs-on:运行器类型
- python-version:Python 版本
- cuda-version:CUDA 版本
- torch-version:PyTorch 版本
- cxx11_abi:C++11 ABI 设置
- upload-to-release:是否上传到 Release
- use-local-version:是否使用本地版本号
11.5 PyPI 发布
- name: Build core package
env:
DG_USE_LOCAL_VERSION: "0"
DG_SKIP_CUDA_BUILD: "1"
run: python setup.py sdist --dist-dir=dist
关键:PyPI 发布使用 DG_SKIP_CUDA_BUILD=1,即不包含任何 CUDA 代码,仅发布 Python 包 + 头文件,用户安装后运行时 JIT 编译。
12. 项目演进时间线
timeline
title DeepGEMM 架构演进
section 2025 Q1
2025.04.18 : 1550 TFLOPS on H800<br/>初始版本发布
2025.05.07 : NVRTC 支持<br/>DG_JIT_USE_NVRTC=1<br/>编译速度 10x 提升
2025.05.14 : Weight gradient 内核<br/>支持 dense/MoE 反向传播
section 2025 Q3
2025.07.20 : 重大重构<br/>支持 SM90/SM100<br/>NVRTC/SASS 优化禁用<br/>低 CPU 开销 JIT
2025.09.28 : MQA Scoring 内核<br/>V3.2 Lightning Indexer 支持<br/>加权 ReLU MQA logits
section 2026 Q1-Q2
2026.04.16 : Mega MoE 发布<br/>FP8xFP4 GEMM 支持<br/>FP4 Indexer<br/>PDL 支持<br/>更快 JIT 编译
12.1 关键架构变更
2025.07.20 — 全面重构 (#112)
"DeepGEMM now supports both SM90/SM100, and has a full refactor with a low-CPU-overhead JIT CPP module."
变更内容:
- 架构支持扩展:从仅 SM90 扩展到 SM90 + SM100
- JIT 重构:NVRTC 和 SASS 后处理优化全部禁用
- 设计决策:NVCC 12.9 自动进行 FFMA 交错,无需手动 SASS 优化
- 未来规划:NVRTC 后续重新支持
2025.05.07 — NVRTC 支持 (#94)
"DeepGEMM now supports NVRTC with up to 10x compilation speedup!"
- 通过
DG_JIT_USE_NVRTC=1启用 - 编译速度提升 10 倍
- 某些情况下可能有性能损失
2026.04.16 — Mega MoE 与 FP4 (#304)
- Mega MoE:融合 EP dispatch + GEMM + SwiGLU + EP combine
- FP8xFP4 GEMM:支持 FP4 权重
- FP4 Indexer:FP4 MQA logits 支持
- PDL:Programmatic Dependent Launch
- 更快 JIT:编译流程优化
12.2 版本号演进
从 git 历史可见:
- 早期版本未在 __init__.py 中标记
- __version__ = '2.4.2'(当前版本)
- 命名曾短暂改为 ds-deep-gemm 后 revert
13. 关键工程洞察
13.1 设计权衡
| 决策 | 优势 | 代价 |
|---|---|---|
| 全 JIT 编译 | 分发体积小、架构适配灵活 | 首次调用有编译延迟 |
| 运行时 cubin 缓存 | 跨进程共享、避免重复编译 | 磁盘空间占用 |
| 轻量 _C.so | 安装快速、兼容性好 | 功能受限(仅 JIT 宿主) |
| 单一 CUDA 宿主入口 | 简化构建、统一接口 | 所有 API 集中在一个模块 |
| 环境变量驱动 | 灵活配置、无需重新编译 | 文档负担、发现性差 |
13.2 与 CUTLASS 的对比
| 特性 | CUTLASS | DeepGEMM |
|---|---|---|
| 编译模式 | AOT(安装时编译) | JIT(运行时编译) |
| 分发大小 | 数百 MB | ~1 MB |
| 架构覆盖 | 编译时确定 | 运行时检测 |
| 模板复杂度 | 高(大量 C++ TMP) | 低(简化抽象) |
| 调度器 | 复杂多层 | 轻量启发式 |
| 第三方依赖 | 仅 CuTe | CuTe + fmt |
13.3 性能优化启示
- JIT 缓存策略:通过内容哈希确保缓存一致性,避免手动清理
- L2 Cache Flush:benchmark 时 8 GB memset 确保冷缓存基准
- 架构条件测试:
test_filter+get_arch_major()实现精准覆盖 - 对称内存:Mega MoE 使用
torch.distributed._symmetric_memory实现零拷贝通信
13.4 潜在改进方向
- 预编译缓存预热:提供脚本预编译常用 shape 的 kernel
- 编译进度指示:长时间 JIT 编译时显示进度
- 缓存大小管理:
KernelRuntimeCache当前无容量限制 - 离线编译模式:支持无 GPU 环境下预生成 cubin
附录 A:构建产物清单
DeepGEMM/
├── build/ # 构建临时目录(gitignore)
│ └── lib.linux-x86_64-3.12/
│ └── deep_gemm/
│ ├── include/ # 复制的 CuTe/cutlass 头文件
│ └── _C.cpython-312-x86_64-linux-gnu.so
├── dist/ # 最终分发目录
│ └── deep_gemm-2.4.2+cu129-torch2.8-cxx11abi0-cp312-linux_x86_64.whl
├── stubs/ # 生成的 .pyi 文件(gitignore)
│ └── _C.pyi
├── deep_gemm/
│ ├── include/ # 符号链接(开发模式)
│ │ ├── cute -> third-party/...
│ │ └── cutlass -> third-party/...
│ └── *.so # 符号链接(开发模式)
└── *.egg-info/ # 构建元数据
附录 B:环境变量速查
# 开发调试
export DG_JIT_DEBUG=1 # 打印 JIT 调试信息
export DG_JIT_PRINT_COMPILER_COMMAND=1 # 显示编译命令
export DG_JIT_DUMP_SASS=1 # 转储 SASS 代码
# 性能分析
export DG_USE_NVIDIA_TOOLS=1 # 跳过内部 profiling
export DG_JIT_WITH_LINEINFO=1 # 嵌入行信息
# 构建控制
export DG_FORCE_BUILD=1 # 强制本地构建
export DG_SKIP_CUDA_BUILD=1 # 跳过 CUDA 构建
export DG_JIT_USE_NVRTC=1 # 使用 NVRTC(更快编译)
# 缓存配置
export DG_JIT_CACHE_DIR=/tmp/dg_cache # 自定义缓存目录
附录 C:测试执行命令
# 运行单个测试
python tests/test_fp8_fp4.py
# 运行 sanitizer(内存检查)
python tests/test_sanitizer.py --funcs test_fp8_fp4.test_gemm --tools memcheck
# 运行 Mega MoE(多进程)
torchrun --nproc_per_node=8 tests/test_mega_moe.py --num-processes 8
# 条件过滤测试
python tests/test_bf16.py # 自动跳过 SM90 不支持的测试
文档生成时间:2026-07-30
基于 DeepGEMM v2.4.2 (commit 7f2a703) 分析