为什么_mm256_unpacklo“跳”一个双词,在文档中在哪里说?

问题描述 投票:0回答:1
我发现

_mm256_unpacklo_epi32

指令有点有趣,并且无法真正将其与文档相关联。
指令执行以下操作:

#include <immintrin.h> #include <iostream> int main() { __m256i a = _mm256_set_epi32(8, 7, 6, 5, 4, 3, 2, 1); __m256i b = _mm256_set_epi32(16, 15, 14, 13, 12, 11, 10, 9); __m256i c = _mm256_unpacklo_epi32(a, b); int* values = (int*)&c; for (size_t i = 0; i < 8 - 1; i++) { std::cout << values[i] << ", "; } std::cout << values[7] << std::endl; }

输出为:

1, 9, 2, 10, 5, 13, 6, 14

对我来说,它似乎是两个源值中的第二低单词“跳”。

这样做的原因是什么?是否有一条指令将源向量的较低128位向量交织在一起?这种行为对我似乎并不有用。

我也不能与文档进行调和:
    https://www.intel.com/content/www/us/en/en/docs/cpp-compiler/developer-guide-guide-guide-guide-guide-guide-2021-10/mmm256-unpacklo--unpacklo-- EPI8-16-32-64.HTML
  • 。在哪里说第二个最低的双字被忽略了?
  • 您链接的文档是如此短,如果您还不知道“高级数据元素被忽略了什么”,则没有用。 不是输入的前128位。
  • SSE SHUFFLES的AVX2版本是两个车道中的两个128位散装。没有数据在128位边界上移动。 即它们是“车道上”的散装,例如avx1
__m256i
c++ simd intrinsics avx2
1个回答
0
投票

vpermilps读取每个128位输入的低64位。 https://www.intel.com/content/www/us/en/en/docs/intrinsics-guide/index.html#techs=mmx,sse_all,sse_all,每128位的64位资料来源:


vpunpackldq

AVX2具有一些车道交叉的散装,例如
DEFINE INTERLEAVE_DWORDS(src1[127:0], src2[127:0]) {
    dst[31:0] := src1[31:0] 
    dst[63:32] := src2[31:0] 
    dst[95:64] := src1[63:32] 
    dst[127:96] := src2[63:32] 
    RETURN dst[127:0]   
}
dst[127:0] := INTERLEAVE_DWORDS(a[127:0], b[127:0])
dst[255:128] := INTERLEAVE_DWORDS(a[255:128], b[255:128])
dst[MAX:256] := 0
(一个矢量内的dwords)和

vpermd

(2输入128位粒度,即时控制),但没有一个粒度小于128-的2输入的人少量。 为此,您需要AVX-512

vperm2i128
(带有shuffle-Control载体)。 指令具有相同的限制,因此,如果您要打开零包装

有时,您实际上并不需要在向量中以特定顺序的数据,例如如果您要稍后再洗牌。 然后,通过零奇数/偶数为零,或者对于2个将奇数元素混合/偶数元素混合的向量可以以可用的方式混合数据。 或者只是打开lo / hi-确实以不同的顺序将所有元素都变成向量。
如果您确实需要从中期望的结果,则可能需要128位的lo/hi和
vpermt2d

pack
这是一个结果,这是一个结果,所以很烂。
当然,如果需要2个包括您所有输入的结果的向量,则使用256位拆包和
vinserti128

将拆卸输出的高2车道结合在一起,因此4个总散装(unvackhi/lo,vinserti128,vperm2i128) )获取

__m256i a, b; __m128i lo = _mm_unpacklo_epi32(_mm256_castsi256_si128(a), _mm256_castsi256_si128(b)); __m128i hi = _mm_unpackhi_epi32(_mm256_castsi256_si128(a), _mm256_castsi256_si128(b)); __m256i c = _mm256_set_m128i(hi, lo); // or _mm256_inserti128_si256(_mm256_castsi128_si256(lo), hi, 1);

_mm256_permute2x128_si256(hi, lo, constant)

。 因此,它的“仅”是AVX-512
c

而不是3x的两倍。

d
是严格的ub口化,并且在GCC和/或Clang中可能会错误地编译。 不要那样做。

PRINTA __M128I变量


最新问题
© www.soinside.com 2019 - 2025. All rights reserved.