在ARM架构中,浮点运算指令是高性能计算的关键组成部分。作为现代处理器架构的重要特性,ARMv8和后续版本提供了丰富的浮点运算指令集,其中FMLS和FMSUB指令因其高效的乘减操作而备受关注。
浮点运算在科学计算、图形处理和机器学习等领域有着广泛应用。与传统标量运算相比,SIMD(单指令多数据)浮点运算能够同时处理多个数据元素,显著提升计算效率。ARM的NEON技术就是基于SIMD的浮点运算扩展,而FMLS和FMSUB正是其中的重要成员。
在实际开发中,合理使用这些浮点指令可以将某些矩阵运算的性能提升3-5倍。特别是在深度学习推理等场景下,这种优化效果更为明显。
FMLS(Floating-point Multiply-Subtract)指令执行浮点乘减操作,其数学表达式可以表示为:
code复制D = D - (N × M)
其中:
指令格式示例:
armasm复制FMLS Vd.4S, Vn.4S, Vm.4S // 向量形式,单精度浮点
FMLS Vd.2D, Vn.2D, Vm.2D // 向量形式,双精度浮点
FMLS指令有多种变体,主要分为两大类:
按元素操作(by element):
允许从第二个源向量的特定元素进行乘减操作。编码格式中包含了元素索引字段,使得可以灵活选择源向量的特定元素。
向量操作(vector):
对整个向量执行乘减操作,是最常用的形式。根据精度又分为:
典型编码结构:
code复制31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
| Q | 0 0 1 1 1 | sz | 1 | Rm | 1 1 0 0 | 1 1 | Rn | Rd | U | o2 |
关键字段说明:
处理器执行FMLS指令时,内部会经历以下步骤:
伪代码表示:
pseudo复制for e = 0 to elements-1 do
element1 = FPNeg(operand1[e])
result[e] = FPMulAdd(operand3[e], element1, operand2[e], FPCR)
end
V[d] = result
FMSUB(Floating-point Fused Multiply-Subtract)是FMLS的扩展版本,主要区别在于:
指令格式示例:
armasm复制FMSUB Sd, Sn, Sm, Sa // 单精度标量形式
FMSUB Dd, Dn, Dm, Da // 双精度标量形式
FMSUB采用典型的浮点指令编码格式:
code复制31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
| 0 0 0 1 1 1 1 | ftype | 0 | Rm | 1 | Ra | Rn | Rd | M | S | o1 | o0 |
关键字段:
FMSUB的执行过程比FMLS更复杂:
伪代码表示:
pseudo复制product = FPMul(N, M, FPCR)
neg_product = FPNeg(product, FPCR)
result = FPAdd(A, neg_product, FPCR)
D = result
矩阵运算:
c复制// 矩阵乘法中的乘减操作
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
C[i][j] -= A[i][k] * B[k][j];
}
}
使用FMLS可以向量化这个内层循环。
数字信号处理:
在FIR滤波器等应用中,乘减操作非常常见。
物理模拟:
计算粒子间相互作用力时经常需要乘减运算。
寄存器分配策略:
指令调度:
armasm复制// 不好的顺序:存在数据依赖
FMLS V0.4S, V1.4S, V2.4S
FMLS V0.4S, V3.4S, V4.4S
// 优化后的顺序:交错独立操作
FMLS V0.4S, V1.4S, V2.4S
FMLS V5.4S, V3.4S, V4.4S
循环展开:
适当展开循环可以减少分支预测失败,同时增加指令级并行度。
非法指令异常:
精度问题:
性能未达预期:
FMLSL(Floating-point Multiply-Subtract Long)执行从半精度到单精度的扩展乘减:
armasm复制FMLSL Vd.4S, Vn.4H, Vm.H[2] // 使用Vm的第2个半精度元素
特点:
FMMLA(Floating-point Matrix Multiply-Accumulate)是ARMv8.6引入的矩阵运算指令:
armasm复制FMMLA Vd.4S, Vn.8H, Vm.8H // 半精度矩阵乘加
优势:
在实测中,使用FMMLA实现3x3矩阵乘法可比标量实现快8-10倍。不过需要注意,这类指令通常需要特定的CPU微架构支持。