SIMD:更通用的随机播放功能

问题描述 投票:0回答:1

[我认为对于not real shuffle,SIMD混洗功能为int32_t,左右部分将分别混洗。

我想要一个真正的随机播放功能,如下所示:

假设我们得到了__m256i,我们想将8 int32_t改组。

__m256i to_shuffle = _mm256_set_epi32(17, 18, 20, 21, 25, 26, 29, 31);

const int imm8 = 0b10101100;

__m256i shuffled _mm256_shuffle(to_shuffle, imm8);

我希望shuffled = {17, 20, 25, 26, -, -, -, -},其中-代表无关的值,它们可以是任何值。因此,我希望将int设置位置的1放置在shuffled中。

(在我们的情况下:17、20、25、26坐在1中带有imm8的位置上。


英特尔提供了这种功能吗?如何有效地实现这种功能?


编辑:-可以忽略。仅需要设置位1的int。

c++ intel simd intrinsics avx
1个回答
0
投票

(我假设您立即倒退(17的选择器应该是低位,而不是高位,并且您的向量实际上是以低元素优先顺序写入的。)

如何有效地实现这种功能?

在这种情况下,使用AVX2 vpermd_mm256_permutevar8x32_epi32)。它需要一个不是立即数的控制向量,才能为8个输出元素保留8个选择器。因此,您必须加载一个常数并将其用作控制操作数。

由于您仅关心输出矢量的下半部分,因此矢量常量只能为__m128i,从而节省了空间。 vmovdqa xmm, [mem]零扩展到相应的YMM向量。用内在函数用C编写此代码可能很不方便,但是_mm256_castsi128_si256应该可以工作。甚至_mm256_broadcastsi128_si256,因为广播负载同样便宜。不过,有些编译器可能会通过进行常量传播将其简化为内存中的实际32字节常量。如果您知道汇编语言,则编译器输出经常令人失望。

如果要在源代码中获取实际的整数位图,则可以使用C ++模板在编译时将其转换为正确的向量常量。 Agner Fog's Vector Class Library(现在是Apache许可的,以前是GPL)具有一些相关的功能,例如,使用C ++模板,根据常量和支持的目标ISA将整数常量转换为单个混合或混合指令序列。但是其随机播放模板采用的是索引列表,而不是位图。

但是我认为您正在尝试询问为什么/如何按原样设计x86洗牌。


英特尔提供了这种功能吗?

是,在带有AVX512F的硬件中(加上AVX512VL以便在256位向量上使用它)。

您正在寻找vpcompressd,它是BMI2 vpcompressd的向量元素等效项。 (但是它将控制操作数作为掩码寄存器值,而不是立即数。)内在函数是pext也可以使用合并到现有向量底部而不是将顶部元素清零的版本。


作为[[立即随机播放,编号

所有x86随机播放都使用一个控件操作数,该操作数具有指向源的索引,而不是保留哪些元素的位图。 (__m256i _mm256_maskz_compress_epi32( __mmask8 c, __m256i a);vpcompressd/q除外)。或者,他们使用隐式控件,例如vpexpandd/q,它从2个输入(低和高半部分的车道内)交错32位元素。

如果您要完全提供带有控制操作数的随机播放,那么任何元素都可以在任何位置结束通常是最有用的。因此,输出不必与输入顺序相同。您的压缩随机播放不具有该属性。

此外,随机播放硬件自然需要每个输出元素都有一个源索引。我的理解是,每个输出元素都由其自己的MUX(多路复用器)馈送,其中MUX需要N个输入元素和一个二进制选择器来选择要输出的那个。 (并且宽度当然与元素的宽度一样。)有关构建复用器的更多讨论,请参见_mm256_unpacklo_epi32

具有选择器列表以外的某种格式的控制操作数,在将其馈送到随机播放硬件之前,需要进行预处理。

[立即,格式为2x1位或4x2位字段,或Where is VPERMB in AVX2?_mm_bslli_si128的字节移位计数。或_mm_alignr_epi8的索引+调零位掩码。没有立即宽度大于8位的SIMD指令。

大概使硬件解码器保持简单。

(或insertps为1x1位,这在事后看来会更好,根本不立即使用。与vextractf128 xmm, ymm, 0 or 1一起使用总是比0差。尽管AVX512确实对vmovdqa xmm, xmm使用与vextractf32x4相同的操作码1x2位立即数的EVEX前缀,所以这可能对解码器的复杂性有所帮助。

无论如何,选择器字段不超过2位的立即混洗

,因为8x 3位将是24位。]] >对于像vextractf32x4_mm256_shuffle_ps)这样的较宽的4x2通道内混洗,相同的4x2位选择器模式将重新用于两个通道。对于像vshufps ymm, ymm, ymm, imm8_mm256_shuffle_pd)这样的2x1较宽的通道内混洗,我们得到4个1位立即数字段,这些字段仍选择通道内。

[具有4个2位选择器vshufpd ymm, ymm, ymm, imm8vshufpd ymm, ymm, ymm, imm8的横穿混洗。它们的工作原理与vpermqvpermpd)完全相同,但是在256位寄存器中使用4个qword元素,而不在128位寄存器中使用4x dword元素。


就缩小/只关心输出的一部分:

普通立即数将需要4个3位选择器来为8个32位源元素之一的每个索引。但是更有可能是8个3位选择器= 24位,因为为什么要设计一个只能写一半半宽度输出的混洗指令? (pshufd xmm除外)。

一般来说,更细粒度的混洗的范例是采用控制向量,

而不是一些时髦的立即编码。
[AVX512确实添加了一些变窄的改组,例如_mm_shuffle_epi32,可将32位元素截断(或使有符号/无符号饱和)降至8位。 (并且所有其他尺寸的组合都可用)。

它们很有趣,因为它们可与内存

目标

一起使用。可能这是由于某些不具有AVX512VL的CPU(例如至强融核KNL / KNM)引起的,因此它们可以[仅]将AVX512指令与ZMM向量一起使用。它们仍然具有AVX1和2,因此您可以压缩为xmm reg,并使用常规的VEX编码存储。但这确实允许使用AVX512F进行窄字节掩码存储,只有将打包数据存储在XMM寄存器中的情况下,AVX512BW才可能进行存储。
[有一些2输入混洗,例如vextractf128 xmm, ymm, 1,它们分别处理输出的下半部分和上半部分,例如输出的低半部分可以从第一源的元素中选择,输出的高半部分可以从第二源寄存器的元素中选择。
© www.soinside.com 2019 - 2024. All rights reserved.