在ARM SVE(Scalable Vector Extension)架构中,浮点向量比较是SIMD运算的核心操作之一。FCM
作为SVE指令集的重要组成部分,FCM
提示:SVE的谓词寄存器机制是其区别于传统SIMD架构的关键创新,它允许程序员只对向量中的特定元素进行操作,这种选择性执行能力在处理稀疏数据时尤为有用。
FCM
assembly复制FCM<cc> <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
其中各参数含义如下:
<Pd>:目标谓词寄存器,用于存储比较结果<Pg>:控制谓词寄存器,决定哪些元素参与比较<Zn>/<Zm>:源向量寄存器,包含待比较数据<T>:数据类型标识符(H/S/D)<cc>:条件码,指定比较类型FCM
| 条件码 | 含义 | 伪指令对应 |
|---|---|---|
| EQ | 等于 | - |
| GE | 大于等于 | FCMLE |
| GT | 大于 | FCMLT |
| NE | 不等于 | - |
| UO | 无序(NaN比较) | - |
值得注意的是,FCMLE和FCMLT实际上是FCM
assembly复制FCMLE <Pd>.<T>, <Pg>/Z, <Zm>.<T>, <Zn>.<T> ≡ FCMGE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
FCMLT <Pd>.<T>, <Pg>/Z, <Zm>.<T>, <Zn>.<T> ≡ FCMGT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>
以FCMEQ(浮点向量等于比较)为例,其指令编码如下:
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 1 1 0 0 1 0 1 size 0 Zm 0 1 1 Pg Zn 0 Pd cmph cmpl
关键字段解析:
FCM
以下是FCM
python复制def FCMcc(Pd, Pg, Zn, Zm, cc):
if not HaveSVE(): raise UNDEFINED
esize = 8 << size # 计算元素大小:16(H),32(S),64(D)
elements = VL // esize # 计算向量元素数量
mask = P[Pg] # 获取谓词掩码
op1 = Z[Zn] if AnyActive(mask) else Zeros() # 源向量1
op2 = Z[Zm] if AnyActive(mask) else Zeros() # 源向量2
result = 0
for e in range(elements):
if GetPredicateBit(mask, e):
# 获取待比较的浮点元素
elem1 = GetVectorElement(op1, e, esize)
elem2 = GetVectorElement(op2, e, esize)
# 根据条件码执行比较
cmp_result = False
if cc == "EQ": cmp_result = FPCompareEQ(elem1, elem2, FPCR)
elif cc == "GE": cmp_result = FPCompareGE(elem1, elem2, FPCR)
elif cc == "GT": cmp_result = FPCompareGT(elem1, elem2, FPCR)
elif cc == "NE": cmp_result = FPCompareNE(elem1, elem2, FPCR)
elif cc == "UO": cmp_result = FPCompareUN(elem1, elem2, FPCR)
SetPredicateBit(result, e, int(cmp_result))
else:
SetPredicateBit(result, e, 0)
P[Pd] = result
浮点比较需要特别处理以下边界情况:
注意:当比较操作涉及NaN时,UO(无序)条件会返回真,而其他条件(EQ/GE/GT/NE)会返回假。这在实现数值算法时需要特别注意。
ARM SVE还提供了与零比较的特殊指令格式:
assembly复制FCM<cc> <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.0
这种形式将向量中的每个元素与浮点零进行比较,减少了需要一个向量寄存器的开销。
与零比较支持的条件码更丰富,包括:
| 条件码 | 含义 | 伪指令对应 |
|---|---|---|
| EQ | 等于零 | - |
| GE | 大于等于零 | - |
| GT | 大于零 | - |
| LE | 小于等于零 | FCMLE |
| LT | 小于零 | FCMLT |
| NE | 不等于零 | - |
与标准向量比较相比,零比较的指令编码有以下变化:
示例:FCMGT与零比较的编码
code复制31...24 |23|22|21...16|15..13|12..10|9..5|4..0
01100101|size|0100001|010|Pg|Zn|1|Pd
FCM
assembly复制// 找出向量中大于阈值的元素
FCMGT p0.s, p1/z, z0.s, z1.s
assembly复制// 检查向量中是否有任何元素小于零
FCMLT p0.s, p1/z, z0.s, #0.0
PTEST p0, p1
BNE has_negative
assembly复制// 检测向量中的NaN值
FCMUO p0.s, p1/z, z0.s, z0.s
结合FCVT指令实现混合精度比较:
assembly复制// 将单精度转换为双精度后比较
FCVT z1.d, p1/m, z0.s // 单精度转双精度
FCMGT p2.d, p1/z, z1.d, z2.d
未生效问题:
NaN处理异常:
性能不达预期:
谓词使用原则:
指令选择建议:
代码可读性:
在实际工程实践中,我发现合理使用FCM