默认的 SIMD 加速 CPU 计算后端。
SIMDTensor
01 Syntax
02 Methods
| Name | Overloads | Summary |
|---|---|---|
| Register | 1 | 把 Tensor.computeKernel 切换为 SIMD 加速的 CPU 实现。 |
| Conv2D | 1 | 卷积前向:按输出行并行,行内沿输出通道向量化。 |
| Conv2DBackwardFilter | 1 | 卷积反向 - 对卷积核的梯度:按 (kh, kw, c) 平面并行,平面内沿输出通道向量化。 |
| Conv2DBackwardInput | 1 | 卷积反向 - 对输入的梯度:按输入行并行。 |
| Axpy | 1 | dst(dstOffset .. +len) += scalar * src(srcOffset .. +len) 的向量化实现。 |
| CeilDiv | 1 | ceil(a / b),其中 b 为正数 |
| Add | 1 | |
| Subtract | 1 | |
| Multiply | 1 | |
| Divide | 1 | |
| Maximum | 1 | |
| Minimum | 1 | |
| Exp | 1 | |
| Log | 1 | |
| Sqrt | 1 | |
| Square | 1 | |
| Abs | 1 | |
| Negate | 1 | |
| Reciprocal | 1 | |
| AddScalar | 1 | |
| MultiplyScalar | 1 | |
| DivideScalar | 1 | |
| Pow | 1 | |
| Clip | 1 | |
| MatMul | 1 | |
| SumAll | 1 | |
| MeanAll | 1 | |
| Sum | 1 | |
| Mean | 1 | |
| Max | 1 | |
| Min | 1 | |
| L2Norm | 1 | |
| StdDev | 1 |
03 Properties
04 Fields
| Name | Overloads | Summary |
|---|---|---|
| MatrixDotThreshold | 2 | 矩阵乘走到 SIMD 行列点积路径的最小规模(m*k*n)。 低于该规模时构建交错数组的开销会超过收益,直接退回标量实现。 |
| ConvParallelThreshold | 2 | 卷积参与并行/向量化计算所需的最少乘加次数;低于该规模时调度开销会超过收益, 直接退回 TensorComputeBase 的标量实现。 |
05 Members
把 Tensor.computeKernel 切换为 SIMD 加速的 CPU 实现。
卷积前向:按输出行并行,行内沿输出通道向量化。
并行粒度取“输出行”(batch × outH);每一行完全由某一个线程独立计算并写入, 线程之间没有任何共享读写,因此结果与线程数无关,可复现。
行内的循环次序改为“先按 (kh,kw,c) 取一个输入标量,再沿输出通道 oc 累加”。 由于后端张量采用 channel-last 布局,卷积核与累加器沿 oc 都是连续的, 这一步正好是一次 axpy 风格的向量运算。对任一输出元素而言,它仍然只沿着 (kh,kw,c) 递增的方向累加,求和顺序与标量实现逐项一致,所以结果逐位相同。
卷积反向 - 对卷积核的梯度:按 (kh, kw, c) 平面并行,平面内沿输出通道向量化。
一个 (kh, kw, c) 三元组恰好对应 dst 之中长度为 outC 的一段连续区间,因此各线程写入 的区域互不相交。每个 dst 元素由唯一的三元组负责,线程把该元素在 (n, oh, ow) 上的 全部贡献按同样的顺序累加完毕后一次写入,与标量实现逐位相同。
卷积反向 - 对输入的梯度:按输入行并行。
每个线程独占一整行输入 (ih),行与行之间的梯度元素互不相交,因此不存在数据竞争, 结果也与线程数无关。
对某个输入行有贡献的输出行 oh 满足 ih = oh * stride + kh - padding 且 kh ∈ [0, filtH),也就是 oh ∈ [(ih + padding - filtH + 1) / stride, (ih + padding) / stride]; 只遍历这个小窗口即可,总计算量与标量实现的 (oh, kh) 遍历相当。
对任一输入梯度元素,贡献按 (oh, ow, oc, kw) 递增的顺序累加,其中 kh 由 (ih, oh) 唯一确定, 因此与标量实现之中 (oh, ow, oc, kh, kw) 的求和顺序逐项一致,结果逐位相同。
Double, Double(), Int32, Double(), Int32, Int32)dst(dstOffset .. +len) += scalar * src(srcOffset .. +len) 的向量化实现。
每个元素只做一次“乘 + 加”,与标量循环的运算顺序完全一致,因此不引入任何数值差异。
Int32, Int32)ceil(a / b),其中 b 为正数
VB 的 \ 是“向零截断”而不是向下取整,因此这里按 ceil(a / b) = -floor(-a / b) 计算,并把负数情形下的截断偏差补回来。
全局默认实例(Tensor.computeKernel 的初始值)
矩阵乘走到 SIMD 行列点积路径的最小规模(mkn)。 低于该规模时构建交错数组的开销会超过收益,直接退回标量实现。
卷积参与并行/向量化计算所需的最少乘加次数;低于该规模时调度开销会超过收益, 直接退回 TensorComputeBase 的标量实现。
Double)Double)Double)Double)