根据文档,支持来自gcc 4.9
指令集的AVX-512
,但我有gcc 4.8
。我目前有这样的代码用于总结一块内存(它保证小于256字节,所以没有溢出问题):
__mm128i sum = _mm_add_epi16(sum, _mm_cvtepu8_epi16(*(__m128i *) &mem));
现在,查看文档,如果我们有剩下的四个字节,我可以使用:
__mm128i sum = _mm_add_epi16(sum,
_mm_mask_cvtepu8_epi16(_mm_set1_epi16(0),
(__mmask8)_mm_set_epi16(0,0,0,0,1,1,1,1),
*(__m128i *) &mem));
(注意,__mmask8
的类型似乎没有记录在我能找到的任何地方,所以我猜...)
但是,_mm_mask_cvtepu8_epi16
是AVX-512
指令,有没有办法复制它?我试过了:
mm_mullo_epi16(_mm_set_epi16(0,0,0,0,1,1,1,1),
_mm_cvtepu8_epi16(*(__m128i *) &mem));
然而,有一个缓存失速,所以直接for (int i = 0; i < remaining_bytes; i++) sum += mem[i];
提供了更好的性能。
答案 0 :(得分:2)
因为我碰巧遇到了这个问题,但如果仍然存在问题,它仍然没有得到答案......
对于您的示例问题,您已走上正确的轨道。
_mm_mullo_epi16
。使用_mm_and_si128
代替按位AND是一个更快的操作,例如_mm_and_si128(_mm_cvtepu8_epi16(*(__m128i *) &mem), _mm_set_epi32(0, 0, -1, -1))
_mm_srli_si128(vector, 8)
_mm_move_epi64
,您有n%16
个字节),这些都不能解决问题。 n
_mm_and_si128(vector, masks[n & 0xf])
只关心向量的低半部分,所以你的例子有些令人困惑 - 也就是说,你不需要掩盖任何东西,因为后来的元素完全被忽略了)在更通用的层面上,掩码操作实际上只是嵌入式_mm_mask_cvtepu8_epi16
(或等效的)。对于归零惯用语,可以使用_mm_blend_epi16
/ _mm_and_si128
轻松模拟它们,如上所示。