为何-fno-signed-zeros编译参数会影响最小值搜索代码的自动向量化?
核心原因
IEEE 754 浮点数标准定义了两种符号的零值(+0和-0),二者的数值比较结果相等,但原始标量代码的更新逻辑和SIMD向量最小值指令的默认行为存在差异,编译器必须收到忽略符号零差异的许可才敢执行向量化。
1. 标量代码的原始语义
按照C语言标准,+0 < -0 和 -0 < +0 的判定结果均为假。原始代码只有在新元素严格小于当前最小值时才会更新最小值:
- 如果当前最小值是
+0,遍历到值为-0的元素时,d < v条件不触发,最小值会保留为+0 - 如果当前最小值是
-0,遍历到值为+0的元素时也不会触发更新,最小值保留为-0
2. SIMD向量最小值指令的行为
主流CPU架构(x86、ARM等)的浮点向量最小值指令(例如x86的minps)处理+0和-0时,会固定返回-0作为最小值,和二者的先后顺序无关。如果编译器在默认规则下直接用这条指令做向量化,就会修改原始代码的行为:原本应该保留的+0会被错误替换为-0,属于不符合标准的错误优化。
3. 编译参数的作用
-ffinite-math-only:告知编译器可以假设输入不存在NaN、无穷值,排除这两类特殊值带来的向量指令和标量逻辑的差异,是向量化的前提-fno-signed-zeros:告知编译器不需要区分+0和-0,二者的差异对程序没有可观测影响。这时候向量最小值指令的行为就和标量逻辑完全一致,编译器可以安全执行自动向量化
内容的提问来源于stack exchange,提问作者geza
相关产品推荐
相关产品推荐

