我有一个巨大的内存块(位向量),在一个内存页中大小为N位,考虑N平均为 5000,即 5k 位来存储一些标志信息。
在某个时间点(超级频繁 - 关键),我需要在整个大位向量中找到第一个位集。现在我每 64 个字都这样做,即在 ) 的帮助下__builtin_ctzll。但是当N增长并且搜索算法无法改进时,可以通过扩展内存访问宽度来扩展此搜索。这是几句话的主要问题
有一条被调用的汇编指令BSF 给出了最高设置位(GCC's __builtin_ctzll())的位置。因此,在x86-64 arch 中,我可以在 64 位字中廉价地找到最高位。
但是通过内存宽度进行缩放呢?
例如,有没有办法用 128 / 256 / 512 位寄存器有效地做到这一点?
基本上我对一些 C API 函数来实现这个感兴趣,但也想知道这个方法是基于什么的。
UPD:至于 CPU,我对这种优化感兴趣,以支持以下 CPU 阵容:
英特尔至强 E3-12XX、英特尔至强 E5-22XX/26XX/E56XX、英特尔酷睿 i3-5XX/4XXX/8XXX、英特尔酷睿 i5- 7XX、英特尔赛扬 G18XX/G49XX(英特尔凌动 N2600、英特尔赛扬 N2807、Cortex-A53/72 可选)
PS在最终位扫描之前提到的算法中,我需要将k(平均 20-40)个N位向量与 CPU AND相加(AND 结果只是位扫描的准备阶段)。这也适用于内存宽度缩放(即比每 64 位字 AND 更有效)
另请阅读:查找第一组
这个问题非常类似于:
用于浮点相等比较的 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 …
据我所知,C++中的整数可以像布尔值一样对待,我们可以有这样的代码:
int a = 6, b = 10;
if (a && b) do something ---> true as both a and b are non-zero
Run Code Online (Sandbox Code Playgroud)
现在,假设我们有:
__m256i a, b;
Run Code Online (Sandbox Code Playgroud)
我需要对 __m256i 中的所有 4 个长变量应用逻辑与 (&&),如果一对非零则返回 true。我的意思是:
(a[0] && b[0]) || (a[1] && b[1]) || ...
Run Code Online (Sandbox Code Playgroud)
我们是否有用于此目的的 AVX 或 AVX2 快速代码?
我找不到任何直接的指令用于此目的,并且肯定,使用按位与 (&) 也是不一样的。
如果有人可以帮助编写一个接收AVX向量的函数并检查它是否包含任何大于零的元素,我将感激不尽.
我编写了以下代码,但它不是最佳的,因为它存储元素然后操纵它.矢量应该作为一个整体进行检查.
int check(__m256 vector)
{
float * temp;
posix_memalign ((void **) &temp, 32, 8 * sizeof(float));
_mm256_store_ps( temp, vector );
int flag=0;
for(int k=0; k<8; k++)
{
flag= ( (temp[k]>0) ? 1 : 0 );
if (flag==1) return 1;
}
free( temp);
return 0;
}
Run Code Online (Sandbox Code Playgroud) 如您所知,前两个是特定于 AVX 的内在函数,第二个是 SSE4.1 内在函数。两组内在函数都可用于检查 2 个浮点向量的相等性。我的具体用例是:
_mm_cmpeq_ps或_mm_cmpeq_pd,然后是_mm_testc_ps或_mm_testc_pd在结果上,使用适当的掩码但是 AVX 为“传统”内在函数提供了等价物,因此_mm_testc_si128在将结果转换为__m128i. 我的问题是,这两个用例中的哪一个会导致更好的性能,以及我在哪里可以找到 AVX 提供了哪些旧的 SSE 指令。