使用SSE高效计算位和

时间:2018-10-23 11:53:12

标签: pointers sse simd

我已经使用SSE进行了计算以提高代码的性能,其中包括minimal working example。我已包含评论和编辑行,以使其尽可能清晰,请询问是否需要任何澄清。

我试图对N个位bit[0], ..., bit[N-1]求和,并将结果以二进制形式写入向量result[0], ..., result[bits_N-1]中,其中bits_N是将N写入二进制形式所需的位数。此和是逐位执行的:每个bit[i]是一个无符号的long long int,并且在其第j位中存储0或1。结果,我进行了64个求和,每个N位, 在平行下。

在80-105行中,我使用64位算术求和。

在第107-134行中,我使用SSE进行了此操作:我将总和bit[0], ...., bit[N/2-1]的前半部分分别存储在_m128i对象BIT[0], ..., BIT[N/2-1]的前64位中。同样,我将bit[N/2], ...., bit[N-1]分别存储在BIT[0], ..., BIT[N/2-1]的后64位中,并对所有BIT求和。到目前为止,一切正常,并且128位总和与64位总和花费相同的时间。但是,要收集最终结果,我需要将两个半部分相加,请参见第125-132行。这需要很长时间,并且使我失去了上交所获得的收益。

我正在2.80 GHz @ gcc 7.2.0的Intel(R)i7-4980HQ CPU上运行此程序。

您知道解决这个问题的方法吗?

1 个答案:

答案 0 :(得分:1)

可以通过movq指令或_mm_storel_epi64 (__m128i* mem_addr, __m128i a);内部存储到内存或_mm_cvtsi128_si64存储到寄存器来简单地存储低部分。

还有一个_mm_storeh_pd对应项,它需要强制转换为pd,并且可能由于混合浮点数和整数而导致停顿。

当然可以使用_mm_shuffle_epi(src, 0x4e)将顶部移到下部,然后使用movq保存。