Tag: sse4

如何并行比较两个以上的数字?

是否可以使用SSE4在一条指令中比较一对以上的数字? 英特尔参考咨询有关PCMPGTQ的内容如下 PCMPGTQ – 比较大于的打包数据 对目标操作数(第一个操作数)和源操作数(第二个操作数)中的压缩四字进行SIMD比较。 如果第一个(目标)操作数中的数据元素大于第二个(源)操作数中的相应元素,则目标中的相应数据元素将设置为全1; 否则,设置为0。 这不是我想要的,因为我希望能够决定哪个整数更大,哪个整数更小。 例如,如果我需要比较 32 with 45 13 with 78 44 with 12 99 with 66 我打算将[32, 13, 44, 99]放在一个向量中,将[45, 78, 12, 66]放在另一个向量中,并在一条指令中使用SSE4进行比较,得到[0, 0, 1, 1] 0,0,1,1 [0, 0, 1, 1]结果(0 – 少,1 – 更大) 但似乎这不是PCMPGTQ所做的。 有关如何在此级别使用并行性来加速此比较的任何建议?

最佳SSE无符号8位比较

我试图找到使用SSE执行8位无符号比较的最多方法(直到SSE 4.2)。 我正在研究的最常见的情况是比较> 0U,例如 _mm_cmpgt_epu8(v, _mm_setzero_si128()) // #1 (这当然也可以被认为是非零的简单测试。) 但我对更一般的情况也有点兴趣,例如 _mm_cmpgt_epu8(v1, v2) // #2 第一种情况可以使用各种不同的方法用2条指令实现,例如与0比较然后反转结果。 第二种情况通常需要3条指令,例如从两个操作数中减去128并执行带符号的比较。 (有关各种3种指令解决方案,请参阅此问题 。) 理想情况下,我正在寻找#1的单指令解决方案,以及#2的双指令解决方案。 如果这些都不可能,那么我也对在现代英特尔CPU(Sandy Bridge,Ivy Bridge,Haswell)上哪种各样的可能的2或3指令实现最有效的想法感兴趣。 到目前为止,案例#2的最佳实现: 比较等于无符号最大值和反转结果: #define _mm_cmpgt_epu8(v0, v1) \ _mm_andnot_si128(_mm_cmpeq_epi8(_mm_max_epu8(v0, v1), v1), \ _mm_set1_epi8(-1)) 两个算术指令+一个按位= 1.33吞吐量。 反转两个参数的符号位(==减去128)并使用带符号的比较: #define _mm_cmpgt_epu8(v0, v1) \ _mm_cmpgt_epi8(_mm_xor_si128(v0, _mm_set1_epi8(-128)), \ _mm_xor_si128(v1, _mm_set1_epi8(-128))) 一个算术指令+两个按位= 1.16吞吐量。 案例#1的最佳实现,源自上面的案例#2实现: 1。 #define _mm_cmpgtz_epu8(v0) \ _mm_andnot_si128(_mm_cmpeq_epi8(v0, _mm_set1_epi8(0)), \ […]

_mm_crc32_u64定义不明确

为什么世界上_mm_crc32_u64(…)定义是这样的? unsigned int64 _mm_crc32_u64( unsigned __int64 crc, unsigned __int64 v ); “crc32”指令总是累加32位CRC,而不是 64位CRC(毕竟,CRC32不是CRC64)。 如果机器指令CRC32 恰好具有64位目标操作数,则忽略高32位,并在完成时填充0,因此没有使用EVER具有64位目标。 我理解为什么英特尔允许在指令上使用64位目标操作数(为了均匀性),但如果我想快速处理数据,我想要一个尽可能大的源操作数(即如果剩下那么多数据,则为64位,尾部较小)并且始终是32位目标操作数。 但内在函数不允许使用64位源和32位目标。 注意其他内在函数: unsigned int _mm_crc32_u8 ( unsigned int crc, unsigned char v ); “crc”的类型不是8位类型,也不是返回类型,它们是32位。 为什么没有 unsigned int _mm_crc32_u64 ( unsigned int crc, unsigned __int64 v ); ? 英特尔指令支持这一点, 这是最有意义的内在因素。 有没有人有可移植的代码(Visual Studio和GCC)来实现后者的内在? 谢谢。 我的猜测是这样的: #define CRC32(D32,S) __asm__(“crc32 %0, %1” : […]