Hotdry.

Article

brush:Rust实现跨平台3D高斯溅射的工程实践

解析brush项目如何用Rust与Burn框架实现CUDA无关的3D重建管道,涵盖WebGPU渲染管线、跨平台二进制构建与WASM编译要点。

2026-05-13systems

在 3D 重建领域,高斯溅射(Gaussian Splatting)已逐渐取代传统神经辐射场成为实时渲染的主流方案。然而绝大多数实现依赖 CUDA 环境,跨平台部署往往意味着复杂的依赖管理。brush 项目另辟蹊径,采用 Rust 生态构建了一套完整的高斯溅射重建引擎,在 AMD/Nvidia/Intel GPU、macOS/Windows/Linux、Android 乃至浏览器端实现统一的功能与性能表现。本文从系统编程视角解析其架构设计,重点关注内存布局、跨平台 GPU 抽象与构建流水线三个维度。

高斯溅射的计算模型与内存布局

高斯溅射的核心数据结构是一组三维高斯分布,每个高斯由均值位置(position)、协方差矩阵(covariance)、不透明度(opacity)和球谐系数(spherical harmonics)构成。brush 将这些数据组织为连续的 GPU 缓冲区。以 Rust 的nalgebra库进行数学抽象为例,一个高斯的协方差矩阵被分解为缩放矩阵 S 与旋转矩阵 R 的乘积 CR=C S R,其中 C 为 Cholesky 分解的输入。这种分解确保协方差矩阵始终保持半正定性,同时将 9 自由度压缩至 7 个可优化参数。

在内存布局上,brush 采用结构体数组(AoS)向量化存储。每个高斯的完整属性(包括 RGB 通道的球谐系数)被打包为固定大小结构体,批量提交至 GPU。渲染时每个像素的 alpha 混合涉及遍历所有高斯并计算视空间投影权重,这一过程对内存带宽极为敏感。brush 在 Burn 框架层面实现自定义算子融合,将 splatter 核与 alpha 预乘合并为单一 CUDA/Metal/Vulkan 内核,减少全局内存访问次数。

Rust 的所有权模型在这里发挥了独特优势:高斯数据的生命周期由智能指针管理,当训练迭代完成或场景切换时,对应的 GPU 缓冲区会被自动释放。相比 Python 生态的 PyTorch 实现,这种确定性析构避免了 CUDA Context 泄漏与显存碎片问题,对于长期运行的移动端推理尤为重要。

Burn 框架:高阶张量抽象与自定义算子

brush 选择 Burn 作为底层 ML 框架,核心诉求是摆脱 CUDA 运行时依赖。Burn 是纯 Rust 实现的神经网络框架,支持将计算图编译为多种后端(CUDA/Metal/WebGPU/Vulkan/CPU)。在高斯溅射场景中,关键算子包括:

  • 球谐函数预计算:将颜色从视角相关球谐基投影至各向同性 RGB,需在 GPU 上执行矩阵乘法。
  • 光栅化权重计算:对于每个像素,将 3D 高斯投影至图像平面并计算覆盖贡献。
  • Alpha 累积与排序:按深度对高斯排序后执行渐进式透明合成。

Burn 提供的tensor抽象使 brush 能够以设备无关方式表达上述计算。具体而言,算子在backend::Backend trait 下实现,后端切换仅需变更泛型参数而不触及核心逻辑。这意味着同一套代码既能编译为 CUDA 加速的桌面端二进制,也能以 WASM 形式在浏览器中运行。

然而 Burn 的图优化策略与 3D 渲染需求存在张力。高斯溅射的反向传播需要访问中间激活值进行梯度计算,这对内存占用提出挑战。brush 的解决方案是将训练流程拆分为前向(渲染)与反向(参数更新)两个独立阶段,中间结果按需物化而非保留完整计算图。这一权衡在移动端内存受限场景下尤为关键。

WebGPU 渲染管线:从桌面到浏览器的抽象层

WebGPU 作为 W3C 标准规范,旨在提供现代 GPU 功能的统一接口,同时避免 WebGL 的遗留复杂性。brush 将 WebGPU 作为跨平台渲染抽象的核心层,在桌面端通过 Native WebGPU 后端绕过了浏览器的安全沙箱限制,在移动端则利用 WebGPU 与底层 Vulkan/Metal 的直接映射实现硬件加速。

WebGPU 的计算管线由wgpu库的 Rust 绑定管理。brush 的渲染 pass 遵循标准模式:创建ComputePipeline、绑定BindGroup(包含高斯缓冲区与临时中间结果)、发起dispatch调用。关键参数如下:

  • 工作组大小设置为 256×1×1,匹配典型 GPU 的 SIMD 宽度与寄存器文件约束。
  • 共享内存使用push constants传递低频参数(如相机内参),减少缓冲区绑定开销。
  • 深度缓冲采用反向 Z 表示法,将远平面映射至 1.0 以提高浮点精度。

WebGPU 的限制之一是缺乏原生的多视图渲染支持,这对立体视觉或全景场景重建构成障碍。brush 通过多次 dispatch 模拟多视图遍历,牺牲部分并行性换取跨平台一致性。

Android 端构建流水线

Android 平台的 GPU 计算面临独特的工具链复杂度。brush 使用 cargo-ndk 管理 Rust 代码的交叉编译,目标架构为 aarch64-linux-android。该工具封装了 NDK 的工具链路径与 sysroot 配置,开发者仅需设置环境变量即可触发交叉编译。

构建流程的典型步骤为:首先通过rustup target add aarch64-linux-android添加 Android 目标架构;其次运行cargo ndk -t arm64-v8a -o crates/brush-app/app/src/main/jniLibs/ build --release生成 native 库;最后通过 Gradle 将.so文件打包至 APK。brush 特别强调 release 模式构建的必要性 ——debug 构建引入的栈展开与符号表在移动端会显著拖累 GPU 调度性能。

Rust FFI 边界的设计需谨慎处理。brush 将 GPU 缓冲区句柄通过 JNI 的jlong传递至 Java 层,而非直接返回指针引用。这种设计隔离了 Rust 的内存管理与 Android 系统的垃圾回收机制,避免跨语言生命周期纠缠。

WASM 编译与浏览器端部署

将 Rust 编译至 WASM 需要 wasm-pack 工具链链。brush 的 WebAssembly 构建产物依赖 WebGPU API,在浏览器中需要浏览器实现方提供 GPU 计算支持。当前仅有 Chrome 134 + 在 Windows 与 macOS 上支持 WebGPU,Firefox 与 Safari 的实现在进行中。

WASM 二进制的大小控制是关键指标。brush 通过链接时优化(LTO)与符号裁剪将二进制压缩至数 MB 量级,兼顾移动网络环境下的加载延迟。运行时依赖方面,WASM 版本仅需加载brush_bg.wasmbrush.js胶水层,无需额外的 ML 运行时 —— 所有算子内联于单一 WASM 模块中。

然而 WASM 的局限性也显而易见:缺乏 64 位整数支持、SIMD 指令集受限、内存上限通常为 2GB。brush 在流式训练场景下通过分块处理(chunked processing)规避大场景内存溢出,同时将球谐阶数限制为 3(对应 15 个系数),减少每高斯的存储开销。

性能对比与工程权衡

brush 项目声称在渲染与训练速度上优于 gsplat 基准实现。性能优势来源包括:

  • 内存布局优化:AoS 向量化使 GPU 合并内存访问成为可能,减少线程束(warp)的分歧。
  • 后端融合:将多个小算子融合为单一大核,减少中间结果的全局内存读写。
  • 确定性析构:避免 Python/PyTorch 的隐式 GC 导致的内存抖动。

然而 Rust 实现的编译时间显著长于 CUDA C++:在 M 系列 Mac 上 release 构建耗时约 10 分钟,Windows 平台因链接器差异可能更慢。调试体验也不如 CUDA 生态成熟 ——Nsight 等工具对 Rust 符号的支持仍在完善中。

对于系统程序员而言,brush 提供了在非 CUDA 环境探索高斯溅射的完整入口。其代码结构清晰展示了 Rust 在 GPU 计算领域的可行性,同时暴露了生态工具链的短板。选择这一技术栈意味着以编译时间换取运行时可靠性,以平台覆盖广度弥补单点性能深度。


参考来源brush GitHub 仓库

systems

内容声明:本文无广告投放、无付费植入。

如有事实性问题,欢迎发送勘误至 i@hotdrydog.com