ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

面向 NPU SIMD 架构的 3DGS Alpha Blending 算子优化:CalcRender 流水并行与两级剪枝设计

2026/9/18 8:23:16 拓冰建站 浏览量
面向 NPU SIMD 架构的 3DGS Alpha Blending 算子优化:CalcRender 流水并行与两级剪枝设计 面向 NPU SIMD 架构的 3DGS Alpha Blending 算子优化CalcRender 流水并行与两级剪枝设计【免费下载链接】cann-recipes-embodied-ai本项目针对具身智能业务中的典型模型、加速算法提供基于CANN平台的优化样例项目地址: https://gitcode.com/cann/cann-recipes-embodied-ai本文基于 CANN 平台 3D 视觉优化样例仓库中的高斯泼溅3DGS渲染实现系统讲解 Alpha Blending 光栅化核心算子CalcRender在 NPU SIMDVector Core架构上的工程化优化。文章围绕 3DGS 渲染流程、指令流水Pipeline并行设计与两级高斯球剪枝三大主题展开并结合 正向算子源码、反向算子源码 与 Python 封装 给出源码级佐证。读完本文你将掌握3DGS Alpha Blending 的数学本质与光栅化流程、SIMD 架构下的流水设计难点、通过多高斯球批量合并计算 Double Buffer 乒乓缓冲提升指令与访存效率的方法以及基于 Tile 与 Sub-Tile 两级剪枝提前终止渲染、并在反向传播中复用剪枝信息的完整实现思路。背景3DGS 渲染为何需要在 NPU 上做算子级优化3D 高斯泼溅3D Gaussian Splatting以空间中的一组 3D 高斯球表达场景渲染时将其投影到图像平面并按深度排序逐像素混合是当前新视角合成的主流方案之一。仓库在 CANN 平台将其落地为一套完整的 NPU 渲染管线核心入口位于 rasterizer.py其调用链为spherical_harmonics计算球谐颜色projection_three_dims_gaussian_fused完成 3D 高斯投影得到 2D 均值、协方差逆矩阵conic与深度flash_gaussian_build_mask构建 tile 与高斯球的包含关系掩码gaussian_sort对每个 tile 内的高斯球按深度排序get_render_schedule做向量核负载均衡调度calc_render即本文主角——执行 Alpha Blending 光栅化将每个 tile 上的高斯球颜色累积到像素。其中calc_render前向对应 calc_render_fwd_double_clip_gsids.cpp反向对应 calc_render_bwd_var_clip_gsids.cppPython 侧通过torch.autograd.Function封装于 calc_render.py。与 GPU 的线程级并行模型不同NPU 采用 SIMD单指令多数据向量计算架构天然适合一条指令处理一片连续数据但代价是无法对单个像素做独立控制流这构成了全文所有优化的出发点。3DGS Alpha Blending 算子流程Alpha Blending 是 3DGS 光栅化中的核心步骤给定特定相机视角与投影平面将空间中 3D 高斯球的颜色表达按透明度加权累积到各个像素从而构建对应视角的渲染图像。其数学公式为$$ C \sum_{i \in N} c_i \alpha_i \prod^{i-1}_{j1}(1-\alpha_j) $$$$ \alpha_i o_i \exp(-\frac{1}{2} \delta ^ T * \Sigma * \delta) $$其中 $c_i$ 为高斯球颜色$o_i$ 为不透明度opacity$\delta$ 为像素与高斯球均值在投影平面上的偏移$\Sigma$ 为 2D 协方差矩阵由 conic 逆矩阵参与计算$\alpha_i$ 即该高斯球对像素的透明度贡献累乘项 $\prod(1-\alpha_j)$ 表示排在更前面更近的高斯球遮挡后的剩余透射率transmittance。整体算法流程如下按 tile 对 vector core 进行切分每个核循环渲染被分配到的 tile 上的所有像素由于累乘操作的存在必须保证对高斯球排序后依次渲染因此使用 for 循环按深度序逐个遍历每个高斯球对每个高斯球并行计算其对 tile 上所有像素的影响计算出 $\alpha$ 值和颜色贡献对每个像素位置更新累积颜色和透明度值。在 正向 kernel 中可以看到这一流程的向量化落地先用Adds/Mul/Muls/Add/Axpy组合计算高斯密度exp(-1/2(c0·dx² 2c1·dx·dy c2·dy²))再乘 opacity 得到 $\alpha$ 并裁剪到 0.999随后更新透射率累积项并做颜色混合。值得注意的细节是前向实现用对数域累加ln1SubAlphaSum ln(1-alpha)配合 Kahan 风格的误差修正error变量来维持浮点精度这一设计在反向传播中同样被复用。SIMD 架构下的实现难点在 SIMD 架构下实现 3DGS Alpha Blending 算法主要面临以下几个难点流水设计复杂由于 SIMD 架构的并行计算特性流水设计需要充分考虑数据依赖和计算顺序确保各个计算单元搬运 MTE、向量计算 V、标量 S能够高效协同工作。高斯球之间以及单个高斯球内部的计算存在严格前后依赖需要在 vector 指令之间插入PipeBarrier保证数据正确性这直接拖低流水效率。内存访问开销与计算开销相互掩盖高斯球数量众多且对于一个 tile 而言参与渲染的高斯球在 GMGlobal Memory中是不连续的需要通过gsIds间接索引导致内存访问开销大影响计算效率必须靠双缓冲等手段将访存延迟与计算重叠。高斯球冗余计算每个高斯球都需要对 tile 上的所有像素进行计算而实际单个高斯球只覆盖很小一块区域导致大量冗余计算影响整体性能。高斯球流水优化指令流水并行多高斯球批量合并降低 PipeBarrier 频率由于高斯球之间以及单个高斯球内部计算的前后依赖特性vector 指令之间经常需要插入PipeBarrier来保证数据正确性导致流水效率较低。根据 msprof op simulator 的仿真结果对 64 个 float 数计算VMuls需要约 15ns而对 2048 个 float 数计算VMuls所需时间并不是 64 个数情形的 32 倍而只需要约 51ns——因为其中包含了指令解码和数据预取的开销。这一指令发射成本被长向量计算摊薄的特性为批量处理提供了理论依据。最开始的逐高斯球流水设计里每处理一个高斯球各步骤运算之间都需要插入PipeBarrier流水效率较低。经过分析发现多个高斯球中没有依赖的部分计算即对 $\alpha$ 值的计算可以合并在一起从而减少PipeBarrier的插入频率。具体做法是将每次处理的高斯球数量增加到 4 个处理完 4 个高斯球后再插入一次PipeBarrier大大减少了同步次数提升了流水效率。这一优化在源码中有直接对应NUM_GS_PER_LOOP 4定义于 calc_render_fwd_double_clip_gsids.cpp主循环以for (; i currOffset - NUM_GS_PER_LOOP; i NUM_GS_PER_LOOP)步进见同文件 L387每次迭代批量搬运 4 个高斯球的属性gsAttr1Ping_~gsAttr4Ping_L389-L392随后对 4 个高斯球共享同一批临时 UB 缓冲区并行计算先批量完成x/y偏移、x2/y2/xy乘积、conic 加权、Exp与 opacity 相乘得到 4 份 $\alpha$L460-L527再依次串行完成 4 个高斯球的颜色贡献累积与透明度更新。为了实现这一优化需要把单个高斯球的计算拆成两个阶段第一阶段计算 $\alpha$ 值可并行处理 4 个高斯球并暂存结果第二阶段计算颜色贡献依次处理这 4 个高斯球更新累积颜色和透明度。代价是 UB 空间占用增加因为需要存储更多中间结果因此必须仔细复用 UB 空间——例如在渲染第 2~4 个高斯球的颜色时复用第 1 个高斯球 $\alpha$ 计算所用的缓冲区。从 SharedBuffInit 可以看到gaussWeight_1与alpha_1、alphaT_共享同一块 UB 地址UB_OFFSET_GS_ALPHA_1正是这一复用策略的体现整个 kernel 将 192KB UBUB_SIZE 192 * 1024L21划分为共享区、ping 区、pong 区与高斯属性区四大部分。Double Buffer 优化乒乓缓冲掩盖访存延迟除流水并行外另一项优化是使用Double Buffer乒乓缓冲提前读取高斯球属性值从而掩盖内存访问开销。具体来说在处理当前批次高斯球的同时提前读取下一批4 个高斯球的属性值并存入第二块 buffer处理下一批时直接从已写好的 buffer 读取避免内存访问延迟暴露在关键路径上。源码层面的对应为UB 中同时维护gsAttr1Ping_~gsAttr4Ping_与gsAttr1Pong_~gsAttr4Pong_两组属性缓冲UbBuffInit并通过ping布尔量与事件pingId_ EVENT_ID6/pongId_ EVENT_ID7L95-L96交替切换SetFlag/WaitFlagHardEvent::MTE3_MTE2/MTE3_V用于控制搬运与向量计算的先后关系如 L310-L313DataCopy提前发起下一批高斯球的 GM→UB 搬运与当前批次的Exp/Mul/Axpy计算重叠执行从而做到搬运与计算并行、延迟互相掩盖。高斯球剪枝设计在 3DGS 渲染过程中许多高斯球对当前 tile 的像素没有贡献导致大量冗余计算。为提升渲染效率仓库设计了两级剪枝机制分别在tile 级别和像素行Sub-Tile级别进行剪枝。Tile 级别剪枝累积透明度达标即终止整块渲染根据渲染公式当累积透明度达到一定阈值时后续高斯球对像素块的贡献可以忽略不计。因此渲染过程中引入 tile 级别的剪枝当某个 tile 的累积透明度达到预设阈值时提前结束对该 tile 的渲染避免后续不必要的计算。具体实现上每次处理完一组高斯球后配合流水优化即处理完 4 个高斯球后检查 tile 的累积透明度是否达到阈值达到则跳出循环结束渲染。受限于 SIMD 架构无法对每个像素单独进行剪枝操作只能在 tile 级别剪枝。因此在阈值检查时必须确保所有像素的累积透明度都达到阈值才能结束渲染。具体实现流程使用CompareScalar函数将 tile 上所有像素的累积透明度与阈值比较生成掩码该指令会按位方式写回掩码表示每个像素是否达到阈值使用ReinterpretCast将掩码向量转为 64 位整数方便后续判断for 循环将掩码整数与UINT64_MAX进行按位与实际为相等判断若结果相等说明所有像素都达到阈值可结束渲染为在反向传播中正确计算梯度记录每个 tile终止渲染的高斯球 ID写回 GM 的gsClipIndex反向梯度传播时从该 ID 处开始继续计算梯度。源码实现位于 calc_render_fwd_double_clip_gsids.cppCompareScalar(clipIs_, T_, 0.01f, CMPMODE::LT, calPixel_)判断当前透射率是否已低于 0.01即不透明度累积达到 0.99 阈值随后ReinterpretCastuint64_t并按clipIs64.GetValue(i_clip) UINT64_MAX逐 64 位块检查全像素达标L425-L432达标则记录gsClipIndex i并clip_break跳出L433-L440。最终该值写回 GM 的gsClipIndexL877-L883供反向算子通过gsClipIndexGm_.GetValue(tileIdx)读取见 bwd kernel。由于 tile 级别剪枝只能在所有像素都满足条件时生效剪枝效果有限。在实验结果分析中其性能收益只有 5~10% 左右。为了进一步提升渲染效率引入了像素行级别的剪枝机制。Sub-Tile 级别剪枝基于高斯球影响范围的像素行剪枝Sub-Tile 级别剪枝基于高斯球影响范围计算每个高斯球在投影平面上的影响范围若某个像素行完全位于影响范围之外则该高斯球对该像素行无贡献可跳过该行的计算。由于 SIMD 架构需要连续地址计算无法对每个像素行单独做细粒度剪枝因此采用对像素行进行剪枝的做法——通过分析高斯球协方差矩阵可计算其在投影平面上的影响范围从而实现像素行级别剪枝。实验评估显示每个高斯球实际只影响约 6×6 的像素大小而当前预设 tilesize 为 32×32因此每个高斯球实际只影响 tile 上约 20% 的像素行——这意味着 80% 的像素行计算都可以被跳过剪枝潜力巨大。具体实现流程在整个 tile 上计算 $\alpha$ 值确定高斯球在投影平面上的影响范围覆盖的像素行范围使用WholeReduceMax计算出每个像素行的 $\alpha$ 最大值使用CompareScalar将每个像素行的最大 $\alpha$ 值与预设阈值比较生成掩码表示每个像素行是否需要进行渲染计算将掩码向量重解释为 64 位整数用位运算判断像素行状态先使用ScalarCountLeadingZero计算掩码整数的前导零数量由于小端存储特性第一个 1 所在位置实际对应最后一个需要渲染的像素行使用ScalarGetCountOfValue1计算掩码整数中 1 的数量表示需要渲染的像素行数量由此得到需要渲染的像素行范围[sta_pix, end_pix)跳过其余计算为在反向传播中正确计算梯度记录每个高斯球实际影响的像素行范围UB 中使用 UInt8 保存每个高斯球的起始/结束像素行索引每存储 1024 个高斯球后将数据写回 GM 空间供反向传播读取。源码对应为 calc_render_fwd_double_clip_gsids.cppWholeReduceMax按像素行归约出 $\alpha$ 最大值L529-L536CompareScalar(..., 0.01f, CMPMODE::GE, ...)生成行级掩码L538-L545随后ScalarCountLeadingZero(alphaMax)得到结束行end_pix、ScalarGetCountOfValue1(alphaMax)得到有效行数cal_pix进而求出起始行sta_pixL549-L552。后续所有颜色混合与透明度更新操作Muls/Ln/Axpy/Add/DataCopy都只作用在[sta_pix, end_pix)裁剪后的连续像素行区间上如 L571-L574实现向量化下的变长计算。剪枝记录方面每处理一个高斯球其(sta_pix, end_pix)以 UInt8 写入alphaClipIndexUB_L560-L561每个高斯球占用NUM_STORE_CLIPINDEX 2字节累积计数alpha_wb_acc达到NUM_STORE_CLIPINDEX * calPixel_即 1024 个高斯球时通过DataCopy批量写回 GM 的alphaClipIndexL402-L414。若某高斯球对当前 tile 完全无贡献calPixel_1 0则写入哨兵值并跳过该高斯球的计算L555-L559进一步压缩冗余。反向传播中的剪枝信息复用两级剪枝产出的gsClipIndextile 终止高斯球 ID与alphaClipIndex每高斯球的像素行范围在反向算子 calc_render_bwd_var_clip_gsids.cpp 中被充分复用反向以逆序遍历高斯球for (i currOffset - 1; i prevOffset; i--)L289其中currOffset直接取自前向记录的gsClipIndex即被剪枝跳过的尾段高斯球完全不再参与梯度计算每个高斯球的像素行范围通过分块读取alphaClipIndex到 UBL297-L298后解析出sta_pix/end_pixL303-L304sta_pix end_pix的高斯球直接continue跳过L305-L307只对有效行区间做梯度重算各属性梯度通过ReduceSum汇总后以SetAtomicAdd原子累加方式写回 GM 的vGsL479-L488保证多个 tile 共享同一高斯球时梯度正确聚合。结合前向的 CalcRender 封装 可知gs_clip_index与alpha_clip_index均通过ctx.save_for_backward保存并在 backward 中传入底层算子构成完整的前后向剪枝信息闭环。该实现的正确性由 test_calc_render_fwd.py 验证测试以 CPU 参考实现含同样的两级剪枝语义与 NPU 算子输出对比使用assertRtolEqual校验渲染颜色与深度的数值一致性。实验结果分析实验场景为包含 13 万个高斯球经过过滤后实际需要渲染的高斯球数仅为 67917 个、训练 30000 个 iters 的数据集。实验中选取的 $\alpha$ 阈值为 0.004不透明度阈值为 0.99各优化组合的评测结果如下流水优化与剪枝设计叠加后正向耗时收益约 10%反向耗时收益约 30%剪枝对反向收益更显著因为反向不再重算被剪枝的高斯球与像素行。优化方法PSNR前向device耗时(ms)反向device耗时(ms)无优化25.0084.80718.710流水优化25.0054.37917.565剪枝优化25.0105.10113.141流水剪枝24.9744.49513.107不同 α 阈值对剪枝效果的影响进一步评估了不同 $\alpha$ 阈值对剪枝效果的影响仅评估没有重新训练。结果表明阈值提高对反向传播过程的收益提升尤为明显在选取阈值为 0.1 时device 反向耗时仅为原来的 7.5%而 PSNR 只下降了 3.3%。这为实际部署中以极小的精度代价换取显著性能收益的阈值选取提供了依据。阈值选取PSNR前向device耗时(ms)反向device耗时(ms)025.0824.37918.7100.00425.0094.49513.1070.0124.9494.35811.2670.0224.8724.2369.8270.0524.6724.1307.9370.124.2743.5391.4100.223.3093.7641.043总结本文围绕 NPU SIMD 架构下的 3DGS Alpha Blending 算子CalcRender梳理了从数学公式、光栅化流程到工程优化的完整链路。核心优化思路可归纳为三点以4 高斯球批量合并降低 PipeBarrier 同步频率、以 ping-pong Double Buffer 将 GM 访存延迟与向量计算重叠、以 Tile Sub-Tile 两级剪枝将全像素全高斯球的冗余计算压缩到影响范围之内并通过gsClipIndex/alphaClipIndex将剪枝信息贯通到反向传播实现前后向一致的性能收益。源码实证表明正向耗时收益约 10%反向耗时收益约 30%在阈值取 0.1 时反向耗时仅为原来的 7.5%而 PSNR 仅下降 3.3%。这套流水并行 剪枝的组合设计可作为在 SIMD 类架构上移植 3DGS 渲染算子的通用参考范式相关完整实现与数值一致性测试分别位于 ops/ascendc/kernels/op_kernel 与 ops/ascendc/tests供进一步研究。【免费下载链接】cann-recipes-embodied-ai本项目针对具身智能业务中的典型模型、加速算法提供基于CANN平台的优化样例项目地址: https://gitcode.com/cann/cann-recipes-embodied-ai创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考