将__m256i设置为两个__m128i值的值

7

因此,AVX从immintrin.h中提供了一个函数,可以将两个__m128i值的串联存储到单个__m256i值中。该函数为:

__m256i _mm256_set_m128i (__m128i hi, __m128i lo)

然而,当我这样使用它时:

__m256i as[2]; __m128i s[4]; as[0] = _mm256_setr_m128i(s[0], s[1]);

我遇到了编译错误:

error: incompatible types when assigning to type ‘__m256i’ from type ‘int’

我真的不太明白为什么会发生这种情况。非常感谢您的帮助!


4
你确定那个函数在这个头文件里吗?当我像你一样在 #include <immintrin.h> 后尝试使用该函数时,我得到了警告信息“implicit declaration of _mm256_set_m128i”。在C语言中,隐式声明意味着编译器假设该函数将返回一个 int,这也可以解释编译器错误。 - R_Kapp
2个回答

12

并非所有的编译器都定义了_mm256_setr_m128i或者_mm256_set_m128i,甚至没有在immintrin.h中定义。因此,我通常会根据需要定义宏,并用适当的#ifdef测试编译器和版本。

#define _mm256_set_m128i(v0, v1)  _mm256_insertf128_si256(_mm256_castsi128_si256(v1), (v0), 1)

#define _mm256_setr_m128i(v0, v1) _mm256_set_m128i((v1), (v0))
  • Intel ICC 11.1及更高版本都有_mm256_set_m128i_mm256_setr_m128i

  • MSVC 2012及更高版本只有_mm256_set_m128i

  • gcc/clang似乎都没有,尽管我还没有检查最新版本以查看是否已经解决此问题。


3
GCC似乎缺少很多“组合”内部函数。我最近发现_mm256_loadu2_m128及其相关函数是从内存进行转置的最佳方法,因为(在ICC上)它编译成两个不使用向量混洗端口的指令。在GCC上,使用内联汇编是获得相同效果的唯一方法。对于AVX512,GCC缺少所有约简内部函数。 - Mysticial
1
@PeterCordes 哦,真不错!我确实在使用 GCC 4.8 进行测试。谢谢! - Mysticial
1
我刚遇到了这个问题。我想要将一个pshufb常量vbroadcastf128到ymm寄存器的两个通道中。但是gcc6.3.1在我尝试的所有方法中都表现得很糟糕。您的宏是最好的选择,编译成vmovdqa+vinserti128。(clang编译为256b向量)。使用gcc的其他尝试:const __m128 tmp = _mm_castsi128_ps(shufmask128); _mm256_castps_si256(_mm256_broadcast_ps(&tmp)) 编译成常量的FP 128b加载,FP 128b存储到堆栈,然后从刚刚存储的副本中进行vinsertf128。如果您能相信,指针转换甚至更糟糕。 - Peter Cordes
1
据我所知,对于gcc而言唯一不那么糟糕的事情就是在 _mm256_set_epi8 中将常量写两遍,或许可以用CPP宏来减少糟糕程度。 :( 或者对于一个洗牌掩码表,加载+插入可能是一个可以接受的代价,但显然比广播加载要差。 - Peter Cordes
2
痛苦,痛苦,痛苦。它出现在gcc 8.1上。它没有出现在gcc 7.3上。请查看源代码:https://github.com/gcc-mirror/gcc/blob/master/gcc/config/i386/avxintrin.h 。_mm256_set_m128i在那里。 - Pierre
显示剩余9条评论

1
我们曾经遇到同样的问题,并使用宏来解决它。
#ifdef __GNUC__ 
#if __GNUC__ < 8
#define _mm256_set_m128i(xmm1, xmm2) _mm256_permute2f128_si256(_mm256_castsi128_si256(xmm1), _mm256_castsi128_si256(xmm2), 2)
#define _mm256_set_m128f(xmm1, xmm2) _mm256_permute2f128_ps(_mm256_castps128_ps256(xmm1), _mm256_castps128_ps256(xmm2), 2)
#endif
#endif

1
_mm256_insertf128_si256 至少和 _mm256_permute2f128_ps 一样便宜,或者至少相应的汇编指令是这样的。我没有检查这对于常量与运行时变量的编译情况。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接