我读过这篇文章和do-denormal-flags-like-denormals-are-zero-daz-affect-comparisons-for-equality,我理解FTZ和DAZ标志的用法和区别。
DAZ应用于输入,FTZ应用于FP操作的输出。
让我感到困惑的是,如果FTZ被设置为,那么在程序集视图中,异常值从何而来?我认为它只能是常量值,既可以作为直接操作数,也可以来自.rodata部分(使用RIP相对寻址访问)。
但是我在我的二进制文件中发现,这些地方没有异常值,但是它仍然受到FP辅助问题的影响,导致性能不佳。
如果我同时设置了DAZ和FTZ,那么问题就消失了,性能也会更好。实际上,在我的源代码中,我甚至没有找到任何非正常的输入。我真的很迷惑不解,负向值是从哪里来的?
顺便问一下,对于指令vmovsd 0x9498(%rip),%xmm0,假设0x9498(%rip)是一个正态值,那么如果我们分别设置FTZ或DAZ,那么在这个指令执行之后xmm0会发生什么呢?
根据我的理解,DAZ会将0x9498(%rip)作为零,并将mov 0移到xmm0;FTZ会将0x9498(%rip)移动到xmm0,发现它是一个逆真,因此将xmm0变为零。我不确定,对吗?
发布于 2020-04-27 12:30:51
次正规是IEEE二进制格式中指数场=0的值。格式化
当FP数学指令(不移动或纯按位的布尔值)读取这样的数字作为输入操作数时,它必须在将尾数与其他操作数排列时,以及在应用指数为0或非零所隐含的尾数的隐式顶部位时,处理该特殊情况。
是的,大多数情况下,对于输出的FTZ是足够的,因为大多数浮点值是其他FP计算的结果。是的,FTZ是必要的,因为普通数字可以创建低于正常值的结果。上的mul/div/add/sub。(添加输入需要相反的符号)。另一个完全四舍五入的IEEE“基本”操作sqrt不能创建子法线,因为它使数字接近于1.0。
最明显的是使用perf record来找出你在哪里得到FP-助攻,并在那里添加一些额外的检查来打印,或者当你在那里发现一个正常值的时候。(然后在该分支中设置一个断点,以便检查情况。)
对于FTZ集来说,除FP数学操作之外,还可能有非穷尽的非正态分布源:
strtod )的FP位模式。nextafter这样的FP位模式的整数操作。也可能是将整数填充到exp的指数字段的double实现内部的一部分。static double foo = DBL_MIN / 4.0;将是编译时的异常。但你可以在.rodata或.data上找到它们。非const非零静态/全局变量在.data中。显然,任何使用整数处理FP位模式的手动操作都可以做到这一点。如果我不花费额外的指令来避免这种情况,如何在没有AVX2的情况下使用字节中的位来设置ymm寄存器中的dword?(vmovmskps的逆)本可以为比较产生异常的输入,但这是一个不寻常的手工矢量化技巧,编译器不会为您所做。
直接操作数
x86没有FP即时性;您必须使用mov rax, imm64 / movq xmm0, rax或类似的。但是编译器不会这样做,因为从.rodata加载通常更有效。
用于指令
vmovsd 0x9498(%rip),%xmm0
vmovsd只是一个负载,总是精确地复制64位;在体系结构上等同于vmovq SIMD-整数加载。
它不通过ALU运行该值,因此MXCSR位对vmovsd、FP洗牌等没有任何影响。只有执行实际FP数学并能引发FP异常的指令才会受到影响。您可以通过查看asm手册条目中的异常部分来判断。例如,roundsd确实遵守DAZ的要求,在按照指定的模式对输入进行舍入之前,可能会将输入舍入为零。
https://stackoverflow.com/questions/61457985
复制相似问题