zT
分享你的 CUDA 心得, 或者问一个 kernel 问题...
📝 写文章 💬 提问 🖼️ 图片 🔗 代码 📊 Benchmark
compileroptimizationpass ✓ 已验证
幂等与不动点:编译器 pass 反复跑的真正含义
从一个 shell 脚本的'幂等'说起——同一个函数反复跑结果不变,这个朴素概念在编译器里有一个精确对应:不动点(fixed point)。本文讲清楚为什么 DCE、常量折叠这种优化 pass 总是写成'loop until no change',以及不动点之外的汇合性、单调性、终止性这几个相关概念。
✓ 已验证
warp 与调度
compileroptimizationpass ✓ 已验证
编译器优化 pass 速查表:30 个名字背后的概念
编译器优化 pass 的名字一大堆——DCE、GVN、LICM、SCCP、SROA……每个都是一个独立的算法 + 一段术语。本文按'本地 / 函数级 / 循环 / 跨函数 / 后端 / 特殊'六类组织,每个 pass 给出英文全称、中文意思、做什么、为什么有用——读 LLVM 源码或自己写 pass 时当词典查。
cuda-oxideintrinsicinline-asm ✓ 已验证
cuda-oxide:从零加一个自定义 PTX intrinsic——五阶段管线 + 两个真实踩坑
走一遍真实流程:在 cuda-oxide 里加一个返回常量 42 的自定义 intrinsic xxx(),最终在 PTX 中通过内联汇编 mov.u32 %r1, 42; 实现。五个 crate 要改、两个错误版本一定会踩、convergent 属性是正确性而不是性能开关。把整套实战拆给你看。
compilerssamem2reg ✓ 已验证
mem2reg 为什么有效:从'看得见所有读写'说起
mem2reg 把'栈上变量 + load/store'提升成 SSA 寄存器值——这是打开后续一切优化的钥匙。但它能这么做,靠的是一个非常脆弱的前提:'编译器看得见这块内存的所有读写'。一旦 alloca 的地址逃逸到 load/store 之外的地方,这个前提就崩了,promote 就会产生错误的程序。本文用三个具体场景把'地址逃逸'讲透。
cuda-oxideirmir ✓ 已验证
cuda-oxide:同一段代码在七层 IR 里长什么样——hello_constant 全程对比
拆完 11 步流程之后,把同一段代码在每个阶段的真实输出并排放一起。整个 hello_kernel(3 行 Rust → 6 行 PTX)横跨 7 层 IR 的对照,加上两个单语句的逐层追踪——*out = 42 和 thread::xxx()。看信息怎么逐层丢失,形态怎么逐层接近硬件。
compilermlirir ✓ 已验证
MLIR 方言的高低层:看意图还是看机制
MLIR 方言的'高低'不是官方分级,而是按抽象层次来理解的。判断标准就一条:它离'人怎么想'近,还是离'机器怎么执行'近?用同一个矩阵乘从一行变成几十行的例子串起来看。
compilerptxcuda ✓ 已验证
PTX 入门:读懂 NVIDIA GPU 的虚拟汇编
PTX 是 NVIDIA GPU 的虚拟 ISA,介于 LLVM IR 和真正的 GPU 机器码 SASS 之间。它跟 x86 完全不同——指令格式统一、寄存器无限、地址空间显式。本文讲清楚 PTX 指令格式、state space(地址空间)、常用指令族,最后用一段 5 行的 hello_kernel PTX 逐行拆解。
compilerssaoptimization ✓ 已验证
mem2reg:从 alloca-load-store 回到 SSA
几乎所有编译器前端都用 alloca-load-store 模型生成中间 IR——简单但冗余。mem2reg(memory-to-register,把'内存槽'升级回'寄存器值')是把这些冗余消掉、恢复 SSA 形式的经典优化。本文讲清楚 promotable alloca 的判定、phi 节点(φ,SSA 里的汇合节点)的插入、它在 cuda-oxide pipeline 里的位置,以及为什么它从'可选'变成了'必需'。
compilerrustrustc ✓ 已验证
Rust 单态化:Instance 类型与惰性实例化
Rust 的单态化跟很多人想的不一样——它不在编译期预先生成每个泛型实例的独立 MIR,而是用 Instance(def + args) 这种'定义 + 参数'的轻量结构,在 codegen 时按需替换。本文讲清楚 Instance 类型、惰性单态化、is_fully_monomorphized 的两个检查,以及 cuda-oxide 怎么用它过滤泛型代码。
compilerptxcuda ✓ 已验证
从 Rust 写 inline PTX 模板
会读 PTX 之后,下一步是从 Rust 里写自己的 PTX——这是实现自定义 GPU intrinsic 的必备技能。本文讲清楚 inline asm 的'模板 + 约束串'两段对应关系、临时寄存器作用域、谓词输出 selp 套路、format! 动态生成的陷阱,以及一个'读 shared memory 比对'的完整合成例子。
cuda-oxiderustrustc ✓ 已验证
cuda-oxide:hello-constant 拆解 05——找 #[kernel] 函数 + BFS 调用图 + stable MIR 转换
拆 hello-constant 系列第五站。codegen_crate 检测到 device code 之后,先靠命名约定(KERNEL_PREFIX 加魔数 246e25db)识别 kernel,worklist BFS 遍历调用图收集所有可达的 device 函数,最后通过 rustc_public 把 internal Instance 转成 stable Instance 喂给 mir-importer。本文讲清楚整条 collector 流程,以及背后那串 246e25db 是怎么来的。
cuda-oxiderustrustc ✓ 已验证
cuda-oxide:hello-constant 拆解 04——codegen_crate 入口接管
拆 hello-constant 系列第四站。终于进入我们自己的代码——librustc_codegen_cuda.so 被 rustc dlopen 之后,__rustc_codegen_backend 返回一个包装了 LlvmCodegenBackend 的对象,后续 trait 调用大多转发,只在 codegen_crate 这一处拦截 device 路径。
cuda-oxiderustmir ✓ 已验证
cuda-oxide:hello-constant 拆解 06——MIR → dialect-mir 翻译(statement 层)
拆 hello-constant 系列第六站。stable MIR 喂进 mir-importer 后,逐函数翻译成 dialect-mir 形式。每个 local 都翻译成栈槽(mir.alloca),每条 statement 翻译成 1-3 条 dialect-mir op。用 *out = 42 这一行对照真实 dump 看完整过程。
cuda-oxiderustmir ✓ 已验证
cuda-oxide:hello-constant 拆解 07——块尾控制流 + intrinsic dispatch
拆 hello-constant 系列第七站。每个 basic block(基本块)末尾的控制流(rustc 内部叫 Terminator,终结符)是 translator 最复杂的一段。本文按 docs/run.log 真实 dump,讲清楚函数调用为什么必须落在块尾、translate_call 的三步流程、try_dispatch_intrinsic 怎么靠 FQDN(完全限定路径名)字符串识别 GPU intrinsic(编译器内建函数)、以及桩函数体为什么根本没翻译。
cuda-oxiderustdialect-mir ✓ 已验证
cuda-oxide:hello-constant 拆解 08——mir-lower:dialect conversion driver
拆 hello-constant 系列第八站。dialect-mir + dialect-nvvm 的混合 IR 整体降级到 dialect-llvm,靠的是 pliron 的 DialectConversion 框架——你声明'我能转换什么 op、什么类型、怎么转换',driver 自动遍历 module。本文讲清楚 trait 分发机制、跟 Step 7 字符串 match 的对比、replace_operation 的关键作用、full conversion 模式,以及降级完之后 IR 真实长什么样。
cuda-oxidellvm-irptx ✓ 已验证
cuda-oxide:hello-constant 拆解 09——llvm-export + llc 生成 PTX
拆 hello-constant 系列第九站。dialect-llvm module 序列化成文本 LLVM IR(.ll),然后调外部 llc 工具用 NVPTX backend 编译成文本 PTX(.ptx)。本文讲清楚 llvm-export 怎么序列化、`llvm_nvvm_*` → `llvm.nvvm.*` 的反向转换、!nvvm.annotations 元数据的作用、llc 调用参数、以及最终 PTX 里每条指令跟 LLVM IR 一一对应的关系。
cuda-oxidecuda-driverhost-runtime ✓ 已验证
cuda-oxide:hello-constant 拆解 10——host binary 启动 + CUDA driver 加载 PTX
拆 hello-constant 系列第十站。device 编译完成,host 端 binary 启动——通过 CUDA driver API 一步步连 GPU、分配显存、加载 PTX(driver 现场 JIT 编译成 SASS)、launch kernel。本文讲清楚 cuda-core 怎么包装 driver API,以及 cuModuleLoad 触发的 JIT 是整条链路里最'魔法'的一步。
cuda-oxidecuda-drivergpu ✓ 已验证
cuda-oxide:hello-constant 拆解 11(完结)——GPU 执行 + 结果回传
拆 hello-constant 系列最终站。cuLaunchKernel 返回后 GPU 接管,256 个线程并行执行 SASS。本文讲清楚 SM 调度 + warp 锁步、printf buffer 的延迟 flush 机制、benign race(良性竞争)、cuStreamSynchronize + cuMemcpyDtoH 的回传链路,以及为什么 thread xxx: 42 在 Output: 42 之前出现。
compilernmlinker ✓ 已验证
nm 符号类型速查
nm 输出每个符号前带一个字母,标记它所在段(Section)和可见性。
cuda-oxiderustnm ✓ 已验证
cuda-oxide:确认 codegen backend 符号导出
用 nm + grep 验证 rustc-codegen-cuda 把 __rustc_codegen_backend 这个入口符号正确导出来了。
cuda-oxiderustdesign-pattern ✓ 已验证
cuda-oxide:用组合代替继承——一个真实例子
面向对象书里讲烂了的 Composition over Inheritance,在 cuda-oxide 的 CudaCodegenBackend 上是怎么落地的——为什么我们不去重写一个 LLVM 后端,而是把它包起来。
compilerrustcrust ✓ 已验证
rustc -Z codegen-backend:替换 Rust 编译器后端
rustc 的 -Z codegen-backend 是 nightly 阶段的插件机制,允许把默认 LLVM 后端换成自定义实现——Cranelift、GCC、甚至 CUDA。详细讲它的协议、加载流程、CodegenBackend trait,以及自己写一个要注意什么。
cuda-oxiderustcompiler ✓ 已验证
cuda-oxide:hello-constant 全流程拆解——导读
用最简单的 hello-constant example,把 cuda-oxide 从一条 cargo 命令到 GPU 输出 42 之间发生的所有事,拆成 11 步逐站讲透。这是开篇——讲清楚我们要拆什么、为什么挑这个例子、整条路线长什么样。
cuda-oxiderustcompiler ✓ 已验证
cuda-oxide:hello-constant 拆解 01——鸟瞰整个管线
拆 hello-constant 系列的第一站。一条 cargo 命令背后启动了两个独立进程、七层 IR 翻译。这一篇画出全景图,后续每篇都会停在图上某个具体方框深入。
cuda-oxiderustcargo ✓ 已验证
cuda-oxide:hello-constant 拆解 02——cargo-oxide driver 进程做了什么
拆 hello-constant 系列第二站。停在全景图最上面那个方框,看 cargo-oxide driver 进程在 spawn rustc 之前到底做了哪些事——找 backend .so、拼 RUSTFLAGS、然后挂起等子进程退出。它不做编译,只做配置。
cuda-oxiderustrustc ✓ 已验证
cuda-oxide:hello-constant 拆解 03——rustc 前端把源码变成 MIR
拆 hello-constant 系列第三站。进入子进程,看 rustc 的前端流程——五段流水线把 src/main.rs 变成 MIR。我们 backend 拿到的输入到底长什么样?为什么 MIR 是恰到好处的过渡点?这一篇讲清楚 backend 的'原料'。
cuda-oxiderustcargo ✓ 已验证
cuda-oxide:rustc backend dylib 是怎么编出来的
聚焦一个 hello-constant 拆解正篇略过的问题:librustc_codegen_cuda.so 到底是怎么编出来的?Cargo.toml 里 dylib、空 [workspace]、#![feature(rustc_private)] 三个不寻常的设计各自解决了什么问题。
cuda-oxiderustcuda ✓ 已验证
cuda-oxide:开篇
用 Rust 直接写 CUDA kernel,编译成 PTX 跑在 GPU 上——cuda-oxide 是什么、为什么值得研究、这个系列要讲什么。
✓ 已验证
安装环境
✓ 已验证
认识 CUDA
✓ 已验证
Hello, CUDA
公告 ✓ 已验证
你好,HelloCUDA
HelloCUDA 上线了——一个入门 CUDA 编程的地方。
✓ 已验证
nvidia-smi
✓ 已验证
nvcc