在高级向量扩展(AVX)中,比较指令如_m256_cmp_ps,最后一个参数是比较谓词.谓词的选择压倒了我.它们似乎是类型,排序,信号的三重奏.例如_CMP_LE_OS是'小于或等于,有序,信令.
对于初学者来说,是否存在选择信令或非信令的性能原因,同样,有序或无序的速度比另一个更快?
什么'非信令'甚至意味着什么?我根本无法在文档中找到这个.任何关于何时选择什么的经验法则?
以下是avxintrin.h的谓词选择:
/* Compare */
#define _CMP_EQ_OQ 0x00 /* Equal (ordered, non-signaling) */
#define _CMP_LT_OS 0x01 /* Less-than (ordered, signaling) */
#define _CMP_LE_OS 0x02 /* Less-than-or-equal (ordered, signaling) */
#define _CMP_UNORD_Q 0x03 /* Unordered (non-signaling) */
#define _CMP_NEQ_UQ 0x04 /* Not-equal (unordered, non-signaling) */
#define _CMP_NLT_US 0x05 /* Not-less-than (unordered, signaling) */
#define _CMP_NLE_US 0x06 /* Not-less-than-or-equal (unordered, signaling) */
#define _CMP_ORD_Q 0x07 /* Ordered (nonsignaling) */
#define _CMP_EQ_UQ 0x08 /* Equal (unordered, non-signaling) */
#define …Run Code Online (Sandbox Code Playgroud) 作为编译器项目的一部分,我必须为x86编写GNU汇编代码来比较浮点值.我试图找到有关如何在线进行此操作的资源,据我所知,它的工作原理如下:
假设我要比较的值是浮点堆栈上的唯一值,那么fcomi指令将比较这些值并设置CPU标志,以便je可以使用...指令.
我问,因为这只会有效.例如:
.section .data
msg: .ascii "Hallo\n\0"
f1: .float 10.0
f2: .float 9.0
.globl main
.type main, @function
main:
flds f1
flds f2
fcomi
jg leb
pushl $msg
call printf
addl $4, %esp
leb:
pushl $0
call exit
Run Code Online (Sandbox Code Playgroud)
即使我认为应该打印"Hallo"也不会打印,如果你切换f1和f2,它仍然不会是一个逻辑上的矛盾.jne并且jl但是似乎做工精细.
我究竟做错了什么?
PS:fcomip只弹出一个值还是同时弹出?
类似于问题gcc的ffast-math实际上做了什么?并且与Clang优化级别的SO问题有关,我想知道在实际条件下优化是做什么clang的-Ofast,以及它们是否与gcc完全不同,或者这是否依赖于编译器依赖于硬件.
根据clang优化级别的公认答案,-Ofast增加了-O3优化:-fno-signed-zeros -freciprocal-math -ffp-contract=fast -menable-unsafe-fp-math -menable-no-nans -menable-no-infs.这似乎完全与浮点数学相关.但是这些优化对于像C++这样的事物来说意味着什么呢?像英特尔酷睿i7这样的CPU上的浮点数通用数学函数以及这些差异有多可靠?
例如,实际上:
该代码std::isnan(std::numeric_limits<float>::infinity() * 0)返回真正的我-O3.我相信这是符合IEEE数学标准的结果.
随着-Ofast不过,我得到一个错误的返回值.此外,该操作(std::numeric_limits<float>::infinity() * 0) == 0.0f返回true.
我不知道这是否与gcc中看到的相同.我不清楚结果如何依赖于结构,也不清楚编译器如何依赖它们,也不清楚是否存在任何适用的标准-Ofast.
如果有人可能会产生类似于一组单元测试或代码公案来解决这个问题,那可能是理想的.我已经开始做这样的事情,但宁愿不重新发明轮子.
我正在编写一个编译器,我必须输出浮点值的分支条件代码.例如,要编译这种代码:
if(a <= b){
//1. DO something
} else {
//2. Do something else
}
Run Code Online (Sandbox Code Playgroud)
当a和b是浮点变量时.如果条件不正确,我只需要跳到2,否则降到1.我正在考虑编译器级别的优化,考虑1和2中的内容.
我需要一些适用于所有比较运算符的东西>,> =,<,<=,==和!=
我发现进行比较的一种方法是使用CMPLTSD(以及其他关系运算符的其他等效指令).但是,我必须使用SSE寄存器,特别是结果,然后我必须在通用寄存器(例如eax)上移动它的值,最后将值与0进行比较.
我还看到UCOMISD指令应该正确设置标志,但显然它不像我想象的那样工作.
那么,处理这样的代码的最佳方法是什么?有没有比我的第一个解决方案更好的指示?
最好的,我的意思是,这个问题的一般解决方案.如果可能的话,我希望代码的行为与对整数进行比较的方式相同(cmp a,b; jge label).当然,我更希望用最快的指令来实现这一目标.
这个问题非常类似于:
用于浮点相等比较的 SIMD 指令(使用 NaN == NaN)
尽管该问题侧重于 128 位向量,并且对识别 +0 和 -0 有要求。
我有一种感觉,我自己可能会得到这个,但英特尔内在指南页面似乎已关闭:/
我的目标是获取一个双精度数组并返回数组中是否存在 NaN。我预计大多数情况下不会有一条路线,并希望该路线具有最佳性能。
最初,我打算对自己进行 4 个双打的比较,反映用于 NaN 检测的非 SIMD 方法(即 NaN 只有值为a != atrue 的值)。就像是:
data *double = ...
__m256d a, b;
int temp = 0;
//This bit would be in a loop over the array
//I'd probably put a sentinel in and loop over while !temp
a = _mm256_loadu_pd(data);
b = _mm256_cmp_pd(a, a, _CMP_NEQ_UQ);
temp = temp | _mm256_movemask_pd(b);
Run Code Online (Sandbox Code Playgroud)
但是,在一些比较示例中,除了比较本身之外,似乎还进行了某种 NaN 检测。我简单地想,如果像这样的东西 _CMP_EQ_UQ …
描述LLVM中比较指令类型的CmpInst::Predicate类型定义"llvm/IR/InstrTypes.h"如下:
enum Predicate {
// Opcode U L G E Intuitive operation
FCMP_FALSE = 0, ///< 0 0 0 0 Always false (always folded)
FCMP_OEQ = 1, ///< 0 0 0 1 True if ordered and equal
FCMP_OGT = 2, ///< 0 0 1 0 True if ordered and greater than
FCMP_OGE = 3, ///< 0 0 1 1 True if ordered and greater than or equal
FCMP_OLT = 4, ///< 0 1 0 0 True …Run Code Online (Sandbox Code Playgroud)