根据文档,从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];
可以提供更好的性能。 最佳答案
当我碰巧碰到这个问题时,如果这仍然是一个问题,它仍然没有得到答案...
对于示例问题,您处于正确的轨道。
_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)
之类的东西,不需要任何内容。其他寄存器/存储器负载。移位可能比AND慢。 _mm_move_epi64
n%16
个字节用于某些任意n
),则以上方法都无法解决。请注意,AVX-512也无法真正解决它。如果您需要处理这种情况,则可以使用一张掩码表和AND(取决于剩余),例如_mm_and_si128(vector, masks[n & 0xf])
_mm_mask_cvtepu8_epi16
只关心 vector 的下半部分,因此您的示例有些困惑-也就是说,您不需要掩盖任何东西,因为稍后的元素会被完全忽略)在更通用的级别上,掩码操作实际上只是嵌入式
_mm_blend_epi16
(或等效代码)。对于归零惯用语,可以使用_mm_and_si128
/ _mm_andnot_si128
轻松模拟它们,如上所示。关于c++ - 模拟AVX-512掩码指令,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42616373/