_mm256_blendv_pd()
查看位置63,127,191和255中的位。是否有有效的方法将uint8_t
的4个低位分散到AVX寄存器的这些位置?有4位,如何产生AVX寄存器的掩码?
或者,是否有一种有效的方式来广播这些位,这样就像_mm256_cmp_pd()
的结果一样,在AVX寄存器的相应64位组件中重复每个位?
指令集是AVX2(Ryzen CPU,如果需要其他功能的话)。
_mm256_blendv_pd()
查看位置63,127,191和255中的位。是否有有效的方法将uint8_t
的4个低位分散到AVX寄存器的这些位置?有4位,如何产生AVX寄存器的掩码?
或者,是否有一种有效的方式来广播这些位,这样就像_mm256_cmp_pd()
的结果一样,在AVX寄存器的相应64位组件中重复每个位?
指令集是AVX2(Ryzen CPU,如果需要其他功能的话)。
最有效的方法是使用包含16个256位条目的查找向量,由uint-8索引。
这是一个很好的解决方案,但需要16 * 32 = 512字节的缓存。 –
I.e.在许多处理器上有两条高速缓存行 - 而那些高速缓存行将是只读的,这对我们有很大的帮助。我敢打赌,当你编译移位,掩码和Ors时,必须将这些位分配到256位矢量表查找将运行得更快,即使它确实需要偶尔的缓存加载。但是,对于这种类型的问题,当然也一样,“哪个更快”的唯一真正答案就是分析。然而,我描述的方法在代码清晰度和可维护性方面明显胜出。 –
x86_64上的高速缓存行通常是64个字节,所以512个字节是8个高速缓存行。 –
显而易见的解决方案:将这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)。
根据具体情况,可能值得做或不做。这取决于。
假设uint8_t
存在于通用寄存器中;的做法是:
PDEP
于四个比特转换为4个字节(最高位)于是我想出了两个版本 - 一个使用内存和其他一个没有:内存
方法:
.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而不是最高位集合)。
@ zx485:在Ryzen上pdep是6个uops。所以这些计数只适用于英特尔CPU。 –
尝试使用'vpmovsxbq'将每个字节的符号位复制到每个qword的高位56位。 –
@PeterCordes:非常感谢。真的很棒的建议。令人遗憾的是,PDEP在Ryzen表现不佳。 – zx485
由于63,127,191和255不是2的幂,所以它们不能是用于指示位位置的掩码。如果他们是索引到一个位向量,那么你至少有255位处理。 'unit8_t'包含8位(因此是'8'),所以你问你是否可以用8位表示255位?这似乎不太可能。你需要纠正这个问题,然后才能得到有意义的答案。 –
如果你是一对一,64,128和256是2的幂,所以它们可能是位掩码,但是192不适合该模式(因为它是64 + 128,但是这是两位)所以...... –
@DaleWilson,这是一个关于AVX(2)技术的问题,它运行256位向量。 'uint8_t'最初有4位。我想将它们移动到指定位置(您不明白:63,127,191和255是基于0的位位置,而不是掩码)到256位AVX寄存器。 –