我正在查看 AVX-512 中的指令集,并注意到一组fixup
指令。一些例子:
_mm512_fixupimm_pd,
_mm512_mask_fixupimm_pd,
_mm512_maskz_fixupimm_pd
_mm512_fixupimm_round_pd,
_mm512_mask_fixupimm_round_pd,
_mm512_maskz_fixupimm_round_pd
这里的“修复”是什么意思?
我正在查看 AVX-512 中的指令集,并注意到一组fixup
指令。一些例子:
_mm512_fixupimm_pd,
_mm512_mask_fixupimm_pd,
_mm512_maskz_fixupimm_pd
_mm512_fixupimm_round_pd,
_mm512_mask_fixupimm_round_pd,
_mm512_maskz_fixupimm_round_pd
这里的“修复”是什么意思?
这是一个很好的问题。英特尔的答案(我的大胆)在这里:
该指令专门用于修复涉及一个源的算术计算结果,以使其符合规范,尽管它通常用于修复多指令序列的结果以反映特殊数字输入。例如,考虑 rcp(0)。输入 0 到 rcp,你应该根据 DX10 规范得到 INF。但是,通过 Newton-Raphson 计算 rcp,其中 x=approx(1/0),会产生不正确的结果。为了解决这个问题,可以在 NR 倒数序列之后使用 VFIXUPIMPS 将结果设置为正确的值(即输入为 0 时的 INF)。
在以下位置查找 VFIXUPIMMPD:
https://software.intel.com/sites/default/files/managed/0d/53/319433-022.pdf
英特尔在他们的“未来扩展”指令集参考手册中的描述有一个通常的Operation
部分,它完全指定了哪些位去哪里。
Intrinsics Guide还复制了该部分,这是对Operation
内部指南中其他一些记录不佳的条目的一个很好的改变。或者它可能是最近添加的。它仍然遗漏了表格和图表。我通常发现 insn ref 手册更有用,但有时在搜索我可能没有想到或不知道的说明时除外。
该指令的操作部分长且难以理解,英文文本描述只是粗略的总结:
使用在第二个源操作数(第二个操作数)的相应四字元素中指定的 32 位、两级查找表执行以双精度浮点格式编码的四字元素的修复带有异常报告说明符 imm8 的源操作数(第三个操作数)
...
两级查找表通过将输入数据编码解码为 8 种令牌类型,对第一个源操作数中的每个 DP FP 输入数据进行修复。为每个标记类型定义了一个响应表,该表将第一个源操作数中的输入编码转换为 16 个响应操作中的一个。
预期的用例是:
rcppd
(或类似的)+ newton-raphson 迭代的结果也许更详细的英文描述将有助于弥合那个非常粗略的摘要和完整的伪代码之间的差距:
对于每个 src 元素:
tsrc
MXCSR.DAZ
= 如果设置,则将非规范化刷新为零。在此之后根本没有使用原始的 src :没有dest=src
操作,只有dest=tsrc
.
归类tsrc
为八种“令牌”类型之一(QNAN、SNAN、零、+1、-Inf、+Inf、负值、正值)。如果 imm8 不为零,则在找到匹配类型的令牌时将触发异常。
使用该类别标记在第三个操作数的相应元素中查找一个动作(这是一个由八个 4 位代码组成的表,每个标记一个)。
动作可以是 dest=dest, dest=tsrc, dest=NaN, dest=+/-Inf, dest=Inf 符号为 tsrc, dest=+/-0, dest=+/-1, dest= 1/2、dest=90.0、dest=pi/2 或 dest=MAX/MIN_FLOAT。有关哪些代码映射到哪些操作,请参阅英特尔的文档。
这个过程是针对每个向量元素单独完成的。
一个典型的用途是将dest=dest
代码用于我们正在修复的结果已经正确的所有情况。请注意,dest
由于操作,即使没有写掩码,它也是一个输入操作数dest=dest
。