我们正在尝试以高性能方式使用不等式运算 <、<=、> 和 >= 来比较两个大小相同的 signed int
值 native 数组。由于比较了很多值,true/false
结果将存储在与输入大小相同的 char
数组中,其中 0x00
表示false
和 0xff
表示 true
。
为此,我们使用了英特尔 IPP 库。问题是我们发现执行此操作的函数名为 ippiCompare_*
,来自图像和视频处理库,仅支持 unsigned char
类型(Ipp8u
)、signed/unsigned short
(Ipp16s/Ipp16u
) 和float
(Ipp32f
)。它不直接支持signed int
(Ipp32s
)
我(只)设想了两种可能的解决方法:
将数组转换为直接支持的类型之一并在更多步骤中执行比较(它会变成一个两倍大小的短数组或四倍大小的字符数组)并合并中间结果。
使用另一个直接支持来自 IPP 或另一个库的
signed int
数组的函数,该函数可以在性能方面做同样的事情。
但可能还有其他创造性的方法......所以我请求你的帮助! :)
PS:使用英特尔 IPP 的优势在于大型阵列的性能提升:它同时使用多值处理器功能和多个内核(可能还有更多技巧)。所以简单的循环解决方案不会像 AFAIK 那样快。
PS2:ippiCompare_* doc 的链接
最佳答案
您可以使用 PCMPEQD 进行比较,然后是 PACKUSDW 和 PACKUSWB。这将是顺理成章的事情
#include <emmintrin.h>
void cmp(__m128d* a, __m128d* b, v16qi* result, unsigned count) {
for (unsigned i=0; i < count/16; ++i) {
__m128d result0 = _mm_cmpeq_pd(a[0], b[0]); // each line compares 4 integers
__m128d result1 = _mm_cmpeq_pd(a[1], b[1]);
__m128d result2 = _mm_cmpeq_pd(a[2], b[2]);
__m128d result3 = _mm_cmpeq_pd(a[3], b[3]);
a += 4; b+= 4;
v8hi wresult0 = __builtin_ia32_packssdw(result0, result1); //pack 2*4 integer results into 8 words
v8hi wresult1 = __builtin_ia32_packssdw(result0, result1);
*result = __builtin_ia32_packsswb(wresult0, wresult1); //pack 2*8 word results into 16 bytes
result++;
}
}
需要对齐的指针,一个可以被 16 整除的计数,一些我因为懒惰/愚蠢而省略的类型转换,当然可能还有很多调试。而且我没有找到 packssdw/wb 的内部函数,所以我只使用了编译器中的内置函数。
关于c++ - signed int 数组的高性能比较(使用英特尔 IPP 库),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1580063/