关于simd:如何选择AVX比较谓词变体

How to choose AVX compare predicate variants

在高级向量扩展(AVX)中,比较指令(如_m256_cmp_ps),最后一个参数是比较谓词。
谓词的选择使我不知所措。
它们似乎是类型,排序,信号的三倍。
例如。 _CMP_LE_OS是"小于或等于有序信令"。

对于初学者来说,是否出于性能原因选择信令或非信令,
并且类似地,有序或无序比另一个更快?

"无信号"甚至意味着什么?
我根本找不到在文档中。
关于何时选择什么的任何经验法则?

以下是来自avxintrin.h的谓词选择:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/* 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 _CMP_NGE_US   0x09 /* Not-greater-than-or-equal (unord, signaling)  */
#define _CMP_NGT_US   0x0a /* Not-greater-than (unordered, signaling)  */
#define _CMP_FALSE_OQ 0x0b /* False (ordered, non-signaling)  */
#define _CMP_NEQ_OQ   0x0c /* Not-equal (ordered, non-signaling)  */
#define _CMP_GE_OS    0x0d /* Greater-than-or-equal (ordered, signaling)  */
#define _CMP_GT_OS    0x0e /* Greater-than (ordered, signaling)  */
#define _CMP_TRUE_UQ  0x0f /* True (unordered, non-signaling)  */
#define _CMP_EQ_OS    0x10 /* Equal (ordered, signaling)  */
#define _CMP_LT_OQ    0x11 /* Less-than (ordered, non-signaling)  */
#define _CMP_LE_OQ    0x12 /* Less-than-or-equal (ordered, non-signaling)  */
#define _CMP_UNORD_S  0x13 /* Unordered (signaling)  */
#define _CMP_NEQ_US   0x14 /* Not-equal (unordered, signaling)  */
#define _CMP_NLT_UQ   0x15 /* Not-less-than (unordered, non-signaling)  */
#define _CMP_NLE_UQ   0x16 /* Not-less-than-or-equal (unord, non-signaling)  */
#define _CMP_ORD_S    0x17 /* Ordered (signaling)  */
#define _CMP_EQ_US    0x18 /* Equal (unordered, signaling)  */
#define _CMP_NGE_UQ   0x19 /* Not-greater-than-or-equal (unord, non-sign)  */
#define _CMP_NGT_UQ   0x1a /* Not-greater-than (unordered, non-signaling)  */
#define _CMP_FALSE_OS 0x1b /* False (ordered, signaling)  */
#define _CMP_NEQ_OS   0x1c /* Not-equal (ordered, signaling)  */
#define _CMP_GE_OQ    0x1d /* Greater-than-or-equal (ordered, non-signaling)  */
#define _CMP_GT_OQ    0x1e /* Greater-than (ordered, non-signaling)  */
#define _CMP_TRUE_US  0x1f /* True (unordered, signaling)  */


有序与无序的关系在于,如果其中一个操作数包含NaN,则比较是否为真(请参阅有序/无序比较是什么意思?)。信令(S)与非信令(Q表示安静吗?)将确定是否在操作数包含NaN的情况下引发异常。

从性能的angular来看,这些都应该是相同的(假设当然不会引发异常)。如果要在出现NaN时收到警报,则需要发信号。至于有序与无序,这都取决于您要如何处理NaN。


当任一操作数为NaN时,有序与无序指示结果值。

有序比较返回NaN操作数的false

  • 1.01.0的_CMP_EQ_OQ给出true(原始等式)。
  • NaN1.0的_CMP_EQ_OQ给出false
  • 1.0NaN的_CMP_EQ_OQ给出false
  • NaNNaN的_CMP_EQ_OQ给出false

无序比较返回NaN操作数的true

  • 1.01.0的_CMP_EQ_UQ给出true(原始等式)。
  • NaN1.0的_CMP_EQ_UQ给出true
  • 1.0NaN的_CMP_EQ_UQ给出true
  • NaNNaN的_CMP_EQ_UQ给出true

信令与非信令之间的差异仅影响MXCSR的价值。要观察效果,??您需要清除MXCSR,执行一个或多个比较,然后从MXCSR中读取(感谢Peter Cordes阐明了这一点!)。

枚举值的顺序非常混乱。将它们放在表格中会有所帮助...

0x10位用于切换信令与否。请注意,在规范操作中,LELT是信令,而EQUNORD不是,因此将0x10位置1会从LE / LT操作中删除信令,并将其添加到EQ / UNORD操作。因为这显然是明智的,而且一点也不令人困惑。