使用simd在双精度数组中查找nan

问题描述 投票:1回答:1

此问题非常类似于:

SIMD instructions for floating point equality comparison (with NaN == NaN)

尽管该问题集中在128位向量上,并且要求标识+0和-0。

我有种感觉,也许我自己就能买到,但是intel内在函数指南页面似乎已经下降了:/

我的目标是获取一个双精度数组,并返回该数组中是否存在NaN。我希望在大多数情况下不会出现这种情况,并且希望该路线具有最佳性能。

最初,我将对自己进行4次加倍的比较,以反映非SIMD方法检测NaN的方法(即a != a为true的仅NaN值)。类似于:

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);

但是,在一些比较示例中,除了比较本身之外,似乎还正在进行某种NaN检测。我曾短暂地认为,好吧,如果_CMP_EQ_UQ之类的东西可以检测到NaN,我可以使用它,然后我可以比较4个双打到4个双打,并同时神奇地看8个双打。

__m256d a, b, c;
a = _mm256_loadu_pd(data);
b = _mm256_loadu_pd(data+4);
c = _mm256_cmp_pd(a, b, _CMP_EQ_UQ);

[这时我意识到我并没有直截了当,因为我可能碰巧将一个非NaN的数字与其自身进行比较(即3 == 3),并以此方式获得成功。

所以,我的问题是,将4个双打与自己进行比较(如上所述)是我能做的最好的,还是有其他更好的方法来确定我的数组是否具有NaN?

c nan sse simd avx
1个回答
0
投票

您要查找的比较谓词是_CMP_UNORD_Q_CMP_ORD_Q来告诉您比较是无序的还是有序的。内在函数指南下降了,但是cmppd的asm文档也列出了谓词,并提供了有关其作用的详细信息。


[确实,如果您期望NaN很少并且想要快速扫描很多非NaN值,则可以将两个不同的向量彼此相对cmppd。如果您关心NaN的位置,则一旦知道两个输入向量中的至少一个输入向量中的至少一个,就可以做一些额外的工作来解决。

[与其他SSE / AVX搜索循环类似,您还可以通过将一些比较结果与cmppd(查找任何无序的)或movemask(检查所有有序的)相结合,来摊销_mm256_or_pd成本。例如。 每个移动掩码/测试/分支检查几个缓存行(4x _mm256_and_pd和2x _mm256d

(glibc的asm _mm256_cmp_pdmemchr使用此技巧。)]
© www.soinside.com 2019 - 2024. All rights reserved.