Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模拟AVX-512掩码指令_C++_Gcc_Sse_Avx512 - Fatal编程技术网

C++ 模拟AVX-512掩码指令

C++ 模拟AVX-512掩码指令,c++,gcc,sse,avx512,C++,Gcc,Sse,Avx512,根据文档,支持AVX-512指令集上的GCC4.9,但我有GCC4.8。我目前有这样的代码,用于对内存块进行求和(保证小于256字节,因此无需担心溢出): 现在,查看文档,如果我们还有,比如说,四个字节,我可以使用: __mm128i sum = _mm_add_epi16(sum, _mm_mask_cvtepu8_epi16(_mm_set1_epi16(0),

根据文档,支持AVX-512指令集上的
GCC4.9
,但我有
GCC4.8
。我目前有这样的代码,用于对内存块进行求和(保证小于256字节,因此无需担心溢出):

现在,查看文档,如果我们还有,比如说,四个字节,我可以使用:

__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));
(注意,
\uuu mmask8
的类型似乎在我能找到的任何地方都没有记录,所以我猜……)

但是,
\u mm\u mask\u cvtepu8\u epi16
是一条
AVX-512
指令,那么有没有办法复制它?我试过:

mm_mullo_epi16(_mm_set_epi16(0,0,0,0,1,1,1,1),
               _mm_cvtepu8_epi16(*(__m128i *) &mem));

然而,有一个缓存暂停,所以只有(inti=0;i<剩余的_字节;i++)sum+=mem[i]提供了更好的性能。

因为我碰巧遇到了这个问题,它仍然没有得到答案,如果这仍然是一个问题的话

对于您的示例问题,您的思路是正确的

  • 乘法运算相对较慢,因此应避免使用
    \u mm\u mullo\u epi16
    。使用
    \u-mm\u和\u-si128
    而不是按位使用,这是一种更快的操作,例如
    \u-mm\u和\u-si128(\u-mm\u-cvtepu8\u-epi16(*(\u-m128i*)&mem),\u-mm\u-set\u-epi32(0,0,-1,-1))
  • 我不知道你说的缓存暂停是什么意思,但是如果内存访问是一个瓶颈,并且编译器不会将上面的常量放入寄存器,那么可以使用类似于
    \u mm\u srli\u si128(vector,8)
    的东西,它不需要任何额外的寄存器/内存加载。换档可能比和慢
  • 如果始终为8字节,则可以使用
    \u mm\u move\u epi64
  • 如果剩余的数量不是固定数量的元素(例如,对于某些任意的
    n
    ,您有
    n%16
    字节),则所有这些都无法解决这种情况。请注意,AVX-512也不能真正解决这个问题。如果您需要处理这种情况,您可以有一个掩码表,并且取决于剩余的内容,例如
    \u mm\u和\u si128(向量,掩码[n&0xf])
  • \u mm\u mask\u cvtepu8\u epi16
    只关心向量的下半部分,因此您的示例有些混乱-也就是说,您不需要屏蔽任何内容,因为后面的元素完全被忽略)

在更一般的层面上,掩码操作实际上只是一个嵌入的
\u mm\u blend\u epi16
(或等效)。对于归零习惯用法,可以很容易地用
\u mm\u和_si128
/
\u mm\u和not_si128
来模拟它们,如上所示。

我不清楚您想要什么。您是否有AVX512硬件,但不支持编译器?并不是说128b(例如
\u mm_mask\u cvtepu8\u epi16
)和256b mask操作需要
AVX-512VL
,而KNL没有。你想要一个只支持SSE的解决方案吗?@Zboson,是的,我现在无法轻松升级编译器。简单的
for
循环没有什么特别的错误,但我只是想知道是否有更好的方法,因为实际的循环体比求和要复杂一些-我有一个圆,正在计算(左、右)和(上、下)两半之间的相对权重。你有什么AVX512硬件?你的硬件到底是什么?@KenY-N:你的CPU是一个Haswell,它有AVX2,所以你可以使用AVX2屏蔽负载,例如,如果这有帮助的话?AVX512可以解决这个问题。你可以做
\uuu mask32=(uint32\u t)-1UL>>((32字节左)和31
,这将编译成整数移位和
kmov
。当然,你也可以使用各种技术在AVX2中生成掩码。看到好的一点,我没有想到。谢谢你的更正!
mm_mullo_epi16(_mm_set_epi16(0,0,0,0,1,1,1,1),
               _mm_cvtepu8_epi16(*(__m128i *) &mem));