docs: backfill T1 build-chain
T1 shipped without a design doc; capture the Rust↔CUDA build chain (build.rs+nvcc, no_cuda cfg pattern, RAII GpuBuffer, gitea↔dash5 flow). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
81
docs/00-build-chain.md
Normal file
81
docs/00-build-chain.md
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
# Phase T1: Rust↔CUDA Build Chain — Design Document
|
||||||
|
|
||||||
|
> 回填文档:T1 随 commit `92acf9f` 落地(scaffold + 构建链路 + vecadd 冒烟测试),
|
||||||
|
> 当时未写文档,此处补记,供后续 Phase 回溯。
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
打通「Rust 调 CUDA」的最小闭环:用 `build.rs` 调 `nvcc` 编 `csrc/*.cu`,
|
||||||
|
经手写 `extern "C"` FFI 链入 Rust;本地无 GPU/nvcc 时仍能 `cargo check`。
|
||||||
|
验收以一个 vector-add kernel 冒烟通过为准。
|
||||||
|
|
||||||
|
## Module Layout
|
||||||
|
|
||||||
|
```
|
||||||
|
xtrain/
|
||||||
|
├── Cargo.toml # workspace
|
||||||
|
├── csrc/
|
||||||
|
│ └── test/vecadd.cu # 冒烟用 c[i]=a[i]+b[i]
|
||||||
|
└── crates/xtrain-cuda/
|
||||||
|
├── build.rs # 检测 nvcc → 编 .cu / 链 cudart,否则发 no_cuda cfg
|
||||||
|
└── src/
|
||||||
|
├── ffi.rs # extern "C" 绑定(cudaMalloc/Memcpy/Free…+ kernel launch)
|
||||||
|
├── error.rs # CudaError + check(code)
|
||||||
|
├── device.rs # device_count / set_device / synchronize
|
||||||
|
└── memory.rs # RAII GpuBuffer(alloc/H2D/D2H/Drop)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Design Decisions
|
||||||
|
|
||||||
|
### `build.rs` 检测 nvcc,缺失则发 `no_cuda` cfg
|
||||||
|
|
||||||
|
```rust
|
||||||
|
if !nvcc_available(&cuda_path) {
|
||||||
|
println!("cargo:warning=nvcc not found — skipping CUDA compilation (host-only build).");
|
||||||
|
println!("cargo:rustc-cfg=no_cuda");
|
||||||
|
return; // 不编 .cu、不链 cudart
|
||||||
|
}
|
||||||
|
// 否则:cc::Build::new().cuda(true)…-gencode=arch=compute_120,code=sm_120
|
||||||
|
```
|
||||||
|
|
||||||
|
- 本地机无 GPU/nvcc → 跳过 CUDA 编译,host 侧 Rust 照常 `cargo check`。
|
||||||
|
- dash5 有 nvcc 12.9 → 实编 `.cu`,目标 `sm_120`(RTX 5090)。
|
||||||
|
- 必须配 `println!("cargo:rustc-check-cfg=cfg(no_cuda)")` 声明自定义 cfg,
|
||||||
|
否则新版 rustc 报 `unexpected_cfgs` warning。
|
||||||
|
|
||||||
|
### `no_cuda` cfg 门控 GPU-only 代码
|
||||||
|
|
||||||
|
GPU 专属的 kernel-launch FFI 与集成测试用 `#[cfg(not(no_cuda))]` 包起来:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#[cfg(not(no_cuda))]
|
||||||
|
unsafe extern "C" {
|
||||||
|
pub fn launch_vecadd_f32(a: *const f32, b: *const f32, c: *mut f32, n: i32, stream: CudaStream);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
测试文件顶用 `#![cfg(not(no_cuda))]` 整体门控。**注意**:`cudaMalloc` 等
|
||||||
|
runtime 符号在 `ffi.rs` 里**不**门控(恒声明),本地只 `cargo check`(不链接)所以无碍;
|
||||||
|
真正链接发生在 dash5(cudart 在)。约定:**本地只 check/fmt,链接+测试都在 dash5**。
|
||||||
|
|
||||||
|
### RAII `GpuBuffer`
|
||||||
|
|
||||||
|
`alloc`/`copy_from_host`(H2D)/`copy_to_host`(D2H),`Drop` 调 `cudaFree`,
|
||||||
|
`unsafe impl Send`。后续张量层在其上搭 device 存储(见 `docs/01-tensor.md`)。
|
||||||
|
|
||||||
|
## 验证方法
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ssh dash5
|
||||||
|
export PATH=/usr/local/cuda/bin:/opt/wjh/.cargo/bin:$PATH
|
||||||
|
cd ~/projects/xtrain && cargo test -p xtrain-cuda -- --nocapture
|
||||||
|
# vecadd OK: a[i]+b[i],c[i]=3i 通过
|
||||||
|
```
|
||||||
|
|
||||||
|
本地(无 GPU):`cargo check` 绿(build.rs 发 `no_cuda`,GPU 测试编译出局)。
|
||||||
|
|
||||||
|
## gitea ↔ dash5 同步流
|
||||||
|
|
||||||
|
- `origin = git@gitea:gahow/xtrain.git`,分支 `main`;git 身份用 `~/.gitconfig`(不 `-c` 覆盖)。
|
||||||
|
- 本地 `git push origin main` → dash5 `cd ~/projects/xtrain && git pull` → export PATH 后构建/测试。
|
||||||
|
- 连 gitea 会打印无害的 `Welcome to VyOS` banner,可忽略。
|
||||||
Reference in New Issue
Block a user