ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

量化编解码器详解:Spirula Studio 如何用 q8/q16 SH 值与梯度量化省下数 GB 显存

量化编解码器详解:Spirula Studio 如何用 q8/q16 SH 值与梯度量化省下数 GB 显存 量化编解码器详解:Spirula Studio 如何用 q8/q16 SH 值与梯度量化省下数 GB 显存【免费下载链接】spirula-studioCross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA.项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studioSpirula Studio 是一款跨厂商的 3D Gaussian Splatting(3D 高斯泼溅)训练工具,从原始照片/视频到 splat 再到纹理网格,全部在一个自包含二进制内完成。它最亮眼的特性之一,就是靠**量化编解码器(quantization codecs)**把 SH 球谐系数、Adam 优化器状态乃至梯度全部压进 q8/q16 整数,从而用 8 GB 显存训练 1000 万个全 SH3 高斯。本文带你读懂这套编解码器的工作原理:q8/q16 值量化、日志域 Adam 状态量化、符号对称梯度量化,以及让 GPU 内核提速近半的转置内存布局。为什么需要量化:8 GB 显存训 1000 万高斯一个带 3 阶球谐(SH3)的高斯要携带 48 个 SH 浮点系数,再加上位置、旋转、缩放、不透明度等属性;而 Adam 优化器还要为每个参数维护两份动量状态(g1、g2)。1000 万个高斯如果全程用 fp32,参数 优化器状态轻松吃掉几十 GB 显存,远超消费级显卡。Spirula Studio 的解法是:参数用 16 位(q16)、状态与梯度用 8 位(q8)存储,读取时按块解码回 fp32。效果是 10M 全 SH3 高斯塞进 8 GB VRAM(README.md 的官方承诺)。配置只需一个开关:src/config/TrainConfig.h 中的quantization_level(0 全 fp32,1 开启量化),映射逻辑在 src/app/TrainerCore.cpp:位宽quantization_level 0quantization_level 1SH 值(sh_value_bits)3216 (q16)SH Adam 状态(sh_optim_bits)328 (q8)非 SH Adam 状态(non_sh_optim_bits)3216 (q16)三个编解码器各司其职1️⃣ q8/q16 值量化:分块 min-max 线性编码SH 参数本体由QuantizedTensorBITS, 256编解码器存储(定义于 src/core/Tensor.h)。核心思想非常简单:把每个高斯的 SH 系数按cell编号(一个 cell 一个高斯 × SH 基函数 × 通道三元组);每 256 个 cell 为一块,块内取 (min, max) 浮点对作为边界表(bounds table);每个值量化成 8 位(0~255)或 16 位(0~65535)整数码q;解码公式:value min (max - min) × (q / QMax),端点精确(0 号码就是 min,最大码就是 max)。于是 48 个 fp32 系数(192 字节/高斯/SH 组)变成 96 字节的 q16 码流,加上少量边界表开销——显存直接减半,且只损失肉眼不可见的精度。2️⃣ Adam 状态量化:对 (u, log s) 联合编码,白捡 20~30 dBAdam 状态直接按 min-max 量化是行不通的:g2(二阶矩)跨数量级分布,线性量化在小值处相对精度极差,恰好是 Adam 归一化最敏感的区域。QuantizedAdamState(见 src/core/Tensor.h)的妙处在于先把 (g1, g2) 变换成两个原始量:u g1 / (sqrt(g2) eps)—— 方向信息;log_s log1p(sqrt(g2) / eps)—— 把开方后的二阶矩映射到日志域。日志映射让所有量级都拥有均匀的相对分辨率,且 0 ↔ 0 固定点保证全零初始化天然解码为零,不需要额外初始化路径。注释中给出了实测收益:这一变换在不增加任何存储的前提下,把单步更新后的 SNR 指标稳定提升 20~30 dB。每个 cell 按 AoS 交错存储两个量化字节(q8:2 字节/cell,q16:4 字节/cell)。3️⃣ 梯度量化:符号对称编码,保住零就是零梯度累加器使用另一套编解码器gradq::Codec(src/core/GradQuant.cuh):块内符号对称量化,码字 ∈ [-QMax, QMax],缩放因子取块振幅a max(|min|, |max|),保证码字 0 精确解码为 0.0。这不是抠细节,而是正确性要求:若用 min-max 编码,视野外高斯的零梯度会解码成半个量子的伪梯度;而 Adam 的m/sqrt(v)会把任何恒定伪梯度归一化成全学习率步长,没被更新的高斯就会随机游走成漂浮噪声。对称编码则把 |v| a/(2·QMax) 的值直接吸附到 0,从根上堵住这个漏洞(详见文件头注释,以及 src/backend/vulkan/shaders/optim_quant.slang 中的 Vulkan 镜像实现)。非 SH 属性的 Adam 状态由 src/core/NonShQuantState.h 统一打包(位置、四元数、缩放、不透明度、DC 各一份 q16 量化缓冲),非 FPBO 路径的 SH 梯度则用 q8。两种内存布局:转置布局如何让内核快近半量化只是省显存,布局决定速度。Spirula Studio 为 packed SH 缓冲定义了两种布局(完整推导见 docs/notes/sh-quant-layout.md):AoS 布局(bounds_stride 256):每 256 个连续 cell 共享一个边界,适合一线程一 cell的按 cell 优化器内核;FPBO 转置布局(pair_pitch 512):每 256 个高斯一个块,两个 cell 挤进一个 32 位字,且字在块内转置排列。转置是关键:FPBO 路径是一线程一高斯,AoS 布局下一个 wave 的 32 个线程读写同一个系数会打到 32 条不同缓存行,转置后只需 2 条。实测(RTX 4080 Super,500 万高斯的自行车场景单步):融合内核从13.8 ms → 8.5 ms(CUDA)、20.3 ms → 13.1 ms(Vulkan),回写也不再需要共享内存暂存中转。量化会损失多少精度?作者把量化当作一等公民来验证,而不是差不多就行:src/backend/tests/densify_parity.cpp 系统性遍历sh_value_bits ∈ {32, 8, 16}与不同优化器位宽的组合,对比 fp32 参考实现;docs/testing.md 记录了 quant-grad、rasterization bwd、FPBO、optimizer 等整条链路的 parity 测试矩阵;量化缓冲随 checkpoint 完整落盘(池内eng.sh_quant.q/eng.sh_quant.qb等槽位),跨位宽恢复时由 src/checkpoint/Adapt.cpp 用同一套编解码函数解码重编码,不存在第二套实现漂移的问题。延伸阅读:关键源码与文档资源说明docs/notes/sh-quant-layout.md两种 packed SH 存储布局的完整推导与实测数据src/core/Tensor.hQuantizedTensor/QuantizedAdamState/QuantizedTensorLog三大编解码器src/core/GradQuant.cuh梯度符号对称量化编解码器(零保持的正确性论证)src/core/NonShQuantState.h非 SH 属性 Adam 状态的 q16 量化缓冲打包src/shaders/harmonics.slangSH 前向内核中的_sh_load_q8/_sh_load_q16解码src/backend/vulkan/shaders/sh_quant.slangVulkan 后端量化加载镜像实现src/app/TrainerCore.cppquantization_level到各位宽的映射docs/architecture.md整体架构,理解量化缓冲在整个训练管线中的位置小结Spirula Studio 的量化编解码器是一整套工程化设计:q16 值量化省参数显存,日志域 Adam 状态量化以零存储成本换来 20~30 dB 信噪比,符号对称梯度量化守住零梯度不被污染的底线,转置内存布局再把读取性能拉回满速。最终,消费级 8 GB 显卡也能从容训练千万级高斯的大场景——这正是开源量化 3DGS 训练器对显存效率给出的完整答案。【免费下载链接】spirula-studioCross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA.项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表