2017-08-30 59 views
2

_mm256_blendv_pd()查看位置63,127,191和255中的位。是否有有效的方法将uint8_t的4个低位分散到AVX寄存器的这些位置?有4位,如何产生AVX寄存器的掩码?

或者,是否有一种有效的方式来广播这些位,这样就像_mm256_cmp_pd()的结果一样,在AVX寄存器的相应64位组件中重复每个位?

指令集是AVX2(Ryzen CPU,如果需要其他功能的话)。

+0

由于63,127,191和255不是2的幂,所以它们不能是用于指示位位置的掩码。如果他们是索引到一个位向量,那么你至少有255位处理。 'unit8_t'包含8位(因此是'8'),所以你问你是否可以用8位表示255位?这似乎不太可能。你需要纠正这个问题,然后才能得到有意义的答案。 –

+0

如果你是一对一,64,128和256是2的幂,所以它们可能是位掩码,但是192不适合该模式(因为它是64 + 128,但是这是两位)所以...... –

+1

@DaleWilson,这是一个关于AVX(2)技术的问题,它运行256位向量。 'uint8_t'最初有4位。我想将它们移动到指定位置(您不明白:63,127,191和255是基于0的位位置,而不是掩码)到256位AVX寄存器。 –

回答

2

最有效的方法是使用包含16个256位条目的查找向量,由uint-8索引。

+0

这是一个很好的解决方案,但需要16 * 32 = 512字节的缓存。 –

+1

I.e.在许多处理器上有两条高速缓存行 - 而那些高速缓存行将是只读的,这对我们有很大的帮助。我敢打赌,当你编译移位,掩码和Ors时,必须将这些位分配到256位矢量表查找将运行得更快,即使它确实需要偶尔的缓存加载。但是,对于这种类型的问题,当然也一样,“哪个更快”的唯一真正答案就是分析。然而,我描述的方法在代码清晰度和可维护性方面明显胜出。 –

+0

x86_64上的高速缓存行通常是64个字节,所以512个字节是8个高速缓存行。 –

2

显而易见的解决方案:将这4位用作查找表的索引。你已经知道了,所以我们试试其他的东西吧。

基于变量移位的方法:将该字节广播到每个qword中,然后将它左移{63,62,61,60},排列msb中的右边位。没有测试过这样的事情:

_mm256_sllv_epi64(_mm256_set1_epi64x(mask), _mm256_set_epi64x(63, 62, 61, 60)) 

还有一个好处,由于负载不依赖于面膜,它可以摆脱循环。

这对Ryzen来说不一定是个好主意,内存中的256位加载的吞吐量比单独的vpsllvq的吞吐量要高(这与Ryzen的大多数256b操作一样是2微妙),但是在这里我们也有vmovq(如果该字节不是来自向量寄存器的话)以及较宽的vpbroadcastq(再次2μops)。

根据具体情况,可能值得做或不做。这取决于。

2

假设uint8_t存在于通用寄存器中;的做法是:

  1. 使用PDEP于四个比特转换为4个字节(最高位)
  2. 传递从32位GPR四个字节到YMM的低部分寄存器
  3. 把值到位(位63,127,191,255)

于是我想出了两个版本 - 一个使用内存和其他一个没有:内存

方法:

.data 
    ; Always use the highest bytes of a QWORD as target/128 means 'set ZERO' 
    ddqValuesDistribution: .byte 3,128,128,128,128,128,128,128, 2,128,128,128,128,128,128,128, 1,128,128,128,128,128,128,128, 0,128,128,128,128,128,128,128 
.code 
    ; Input value in lower 4 bits of EAX 
    mov  edx, 0b10000000100000001000000010000000 
    pdep eax, eax, edx 
    vmovd xmm0, eax 
    vpshufb ymm0, ymm0, ymmword ptr [ddqValuesDistribution] 

在上的Haswell和SKYLAKE微架构5个微指令这一次出来。


无记忆变量方法(改进得益于@Peter科尔德):(!)

mov edx, 0b10000000100000001000000010000000 
    pdep eax, eax, edx 
    vmovd xmm0, eax 
    vpmovsxbq ymm0, xmm0 

在上的Haswell和SKYLAKE微架构和4个微指令这一个出来可以通过移动能够进一步提高EDX中的面具变为一个变量。
输出与第一个版本不同(全部是1而不是最高位集合)。

+0

@ zx485:在Ryzen上pdep是6个uops。所以这些计数只适用于英特尔CPU。 –

+0

尝试使用'vpmovsxbq'将每个字节的符号位复制到每个qword的高位56位。 –

+0

@PeterCordes:非常感谢。真的很棒的建议。令人遗憾的是,PDEP在Ryzen表现不佳。 – zx485