内核融合
通过组合多个算子为单个内核来提升性能。
概述
内核融合是一种优化技术,将多个连续的神经网络操作合并为一个 WebGPU 计算着色器。这减少了:
- GPU 内核启动开销
- 中间内存分配
- 内存带宽使用
Conv2dBiasReLU 融合算子
最常见的融合是 Conv2D → AddBias → ReLU:
typescript
import { Conv2dBiasReLUOperator } from 'tiny-dl-inference';
const convBiasRelu = new Conv2dBiasReLUOperator(context);
const output = await convBiasRelu.forward([input, weights, bias]);1
2
3
4
2
3
4
性能对比
| 方法 | 耗时 | 内存分配 |
|---|---|---|
| 分离算子 | ~3.2ms | 2 个中间张量 |
| 融合算子 | ~1.8ms | 无中间张量 |
加速比:约 1.8 倍
融合最佳实践
何时融合
✅ 适合融合的情况:
- 逐元素操作(ReLU、Sigmoid、Tanh)
- 偏置加法
- 批量归一化(推理阶段)
- 逐点卷积
❌ 不适合融合的情况:
- 需要中间输出的调试
- 动态操作选择
- 内存充足的简单模型
融合原则
- 识别模式:查找常见的算子序列
- 分析瓶颈:测量是计算受限还是内存受限
- 增量融合:从最关键的开始,逐步融合
- 验证正确性:确保融合后输出与分离版本匹配
实现融合算子
创建自定义融合算子的步骤:
typescript
class Conv2dBiasReLUOperator extends Operator {
protected compileShader(): string {
return /* wgsl */`
@compute @workgroup_size(8, 8)
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
// 1. 执行卷积
// 2. 添加偏置
// 3. 应用 ReLU
// 单内核中的所有操作
}
`;
}
async forward(inputs: Tensor[], params?: OperatorParams): Promise<Tensor> {
this.ensureInitialized();
// 执行融合计算
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18