Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/68.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/sse掩码过渡到avx512掩码?_C++_Sse_Avx_Avx512 - Fatal编程技术网

C++ 什么是「;“正确”;如何从avx/sse掩码过渡到avx512掩码?

C++ 什么是「;“正确”;如何从avx/sse掩码过渡到avx512掩码?,c++,sse,avx,avx512,C++,Sse,Avx,Avx512,我有一些现有的avx/sse口罩,我是用老方法得到的: auto mask_sse = _mm_cmplt_ps(a, b); auto mask_avx = _mm_cmp_ps(a, b, 17); 在某些情况下,当混合使用旧的avx代码和新的avx512代码时,我想将这些旧式掩码转换为新的avx512\uu mmask4或\uu mmask8类型 我试过这个: auto mask_avx512 = _mm_cmp_ps_mask(sse_mask, _mm_setzero_ps(), 2

我有一些现有的avx/sse口罩,我是用老方法得到的:

auto mask_sse = _mm_cmplt_ps(a, b);
auto mask_avx = _mm_cmp_ps(a, b, 17);
在某些情况下,当混合使用旧的avx代码和新的avx512代码时,我想将这些旧式掩码转换为新的avx512
\uu mmask4
\uu mmask8
类型

我试过这个:

auto mask_avx512 = _mm_cmp_ps_mask(sse_mask, _mm_setzero_ps(), 25/*nge unordered quiet*/);
它似乎适用于普通的比较输出,但我不认为它能够正确捕获可以与sse4.1
\u mm\u blendv\u ps
一起使用的正NAN

还有一个很好的老式
\u mm\u movemask\u ps
,但这看起来像是将掩码完全放在一个通用寄存器中,我需要将其与
\u cvtu32\u mask8
链接,以将其拉回到一个专用掩码寄存器中

有没有更干净的方法直接将符号位从旧式掩码中拉到k寄存器中

示例代码: 下面是一个示例程序,按照我上面提到的第一种方式进行掩码转换

#include "x86intrin.h"
#include <cassert>
#include <cstdio>

int main()
{
    auto a = _mm_set_ps(-1, 0, 1, 2);
    auto c = _mm_set_ps(3, 4, 5, 6);

    auto sse_mask    = _mm_cmplt_ps(a, _mm_setzero_ps());
    auto avx512_mask = _mm_cmp_ps_mask(sse_mask, _mm_setzero_ps(), 25);

    alignas(16) float v1[4];
    alignas(16) float v2[4];
    _mm_store_ps(v1, _mm_blendv_ps(a, c, sse_mask));
    _mm_store_ps(v2, _mm_mask_blend_ps(avx512_mask, a, c));

    assert(v1[0] == v2[0]);
    assert(v1[1] == v2[1]);
    assert(v1[2] == v2[2]);
    assert(v1[3] == v2[3]);
    return 0;
}
#包括“x86intrin.h”
#包括
#包括
int main()
{
自动a=_mm_set_ps(-1,0,1,2);
自动c=_mm_set_ps(3,4,5,6);
自动sse_掩码=_mm_cmplt_ps(a,_mm_setzero_ps());
自动avx512_掩码=_mm_cmp_ps_掩码(sse_掩码,_mm_setzero_ps(),25);
alignas(16)浮动v1[4];
alignas(16)浮动v2[4];
_mm_存储_ps(v1,_mm_blendv_ps(a、c、sse_掩码));
_mm_-store_-ps(v2,mm_-mask_-blend_-ps(avx512-mask,a,c));
断言(v1[0]==v2[0]);
断言(v1[1]==v2[1]);
断言(v1[2]==v2[2]);
断言(v1[3]==v2[3]);
返回0;
}

首先使用AVX-512内部比较来获得AVX-512掩码(如
\u mm\u cmp\u ps\u掩码
);这将比比较成一个向量然后转换它要有效得多,除非编译器为您优化了这种低效。(考虑使用一个包装器库,比如试图消除差异。VCL许可证最近从GPL更改为Apache。)


但是如果您真的需要它(例如,在完成优化之前作为权宜之计),您不需要FP比较\um\u cmp\u ps生成一个
\u m128
结果,但它实际上不是浮点向量1。全是一位/全是零位。您只需要位,因此您正在寻找与
vmovmskps
等效的AVX-512,但要将其放入
k
寄存器,而不是GP整数。i、 e.对于32位源元素

   __m128 cmpvec = _mm_cmplt_ps(v, _mm_setzero_ps() );
   __mmask8 cmpmask = _mm_movepi32_mask( _mm_castps_si128(cmpvec) );   // <----

// equivalent to comparing into a mask in the first place:
   __mmask8 cmpmask = _mm_cmplt_ps_mask(v, _mm_setzero_ps(), _CMP_LT_OQ);

// equivalent to (if I got this right)
   __mmask8 cmpmask = _mm_fpclass_ps_mask(v, 0x40 | 0x10);  // negative | negative_inf
\uuuum128 cmpvec=\umm\ucmplt\ups(v,\umm\usetzero\ups());

__mmask8 cmpmask=_mm_movepi32_mask(_mm_castps_si128(cmpvec));//你看了吗?@PaulR看起来很有希望,但我不认为这比比较零无序更能给我带来什么,因为负数
FinNeg_res(cid:197)NegNum AND NOT(ExpAllOnes)AND NOT(ZeroNumber);//-有限的
排除nan/inf和nan
qNaN_res(cid:197)expallone和NOT(mantallzero)和SignalingBit;;//qNaN
忽略符号entirely我知道我“应该”首先只是生成新样式的遮罩。但是这是一堆在多个ISA扩展中共享的模板代码的深处,所以现在我只想让avx和avx512代码玩得很好我猜,因为我们是skylake-x或更新版本,我不需要担心类型双关的绕过延迟?或者,由于它的公正性,它更不值得关注masks@SteveCox:在SKX上,旁路延迟最差为1个周期,Agner Fog表示VPMOVD2M在端口0上运行,延迟为2个周期,而其他进入掩码操作的延迟为3个周期,因此最差情况下,VPMOVD2M会自行付费。我不知道他是如何测量2的,比如他创造了什么样的dep链;他的指令表倾向于任意划分跨越域边界的指令之间的延迟。更为保守,并向您展示他们使用的dep链。虽然使用掩码并没有那么糟糕,因为掩码和向量都可以作为同一条指令的输入。@SteveCox:但是,是的,可能存在旁路延迟,这取决于
vpmovd2m
执行单元是否同时连接到FP和整数旁路网络,或者其他执行单元显然不是这样。(例如,端口5上的位布尔和洗牌单元,而不是端口0和1上的位布尔单元,如英特尔优化手册中所述。)顺便说一句,对于像我这样在浏览时找不到该指令(以及fpclass)的人,可以在“杂项”下使用其他几个掩码操作函数找到它子节,而不是“面具”子节