__m256类型的intel内在函数问题

我正在尝试测试一些英特尔内部函数,看看它们是如何工作的。 所以,我创建了一个函数来为我做这个,这是代码:

void test_intel_256() { __m256 res,vec1,vec2; __M256_MM_SET_PS(vec1, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0); __M256_MM_SET_PS(vec1, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0); __M256_MM_ADD_PS(res,vec1,vec2); if (res[0] ==9 && res[1] ==9 && res[2] ==9 && res[3] ==9 && res[4] ==9 && res[5] ==9 && res[6] ==9 && res[7] ==9 ) printf("Addition : OK!\n"); else printf("Addition : FAILED!\n"); } 

但后来我收到了这些错误:

 error: unknown type name '__m256' error: subscripted value is neither array nor pointer nor vector error: subscripted value is neither array nor pointer nor vector error: subscripted value is neither array nor pointer nor vector error: subscripted value is neither array nor pointer nor vector error: subscripted value is neither array nor pointer nor vector error: subscripted value is neither array nor pointer nor vector error: subscripted value is neither array nor pointer nor vector error: subscripted value is neither array nor pointer nor vector error: subscripted value is neither array nor pointer nor vector 

这意味着编译器没有识别__m256类型,因此他无法将res视为浮点数组。 我包括这些库mmintrin.hemmintrin.hxmmintrin.h ,我正在使用eclipse Mars

所以我想知道的是问题是来自编译器还是硬件或其他东西? 我该如何解决? 谢谢!

MMX和SSE2是x86-64的基线,但AVX不是。 您需要专门启用AVX,而不是SSE2。

-march=haswell或你实际拥有的任何CPU构建。 或者只使用-mavx

请注意,使用默认tune=generic gcc -mavx会将256b loadu / storeu内在函数拆分为vmovups xmm / vinsertf128 ,如果您的数据实际上在大多数情况下实际对齐,则会很糟糕,特别是在具有有限shuffle-port吞吐量的Haswell上会很糟糕。

如果您的数据确实不对齐,那么对Sandybridge和Bulldozer家族来说是好事。 请参阅https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80568 :它甚至会影响AVX2矢量整数代码,即使所有AVX2 CPU(挖掘机和Ryzen除外)都受到此调整的干扰。 tune=generic没有考虑启用了什么指令集扩展,并且没有tune=generic-avx2

您可以使用-mavx2 -mno-avx256-split-unaligned-load -mno-avx256-split-unaligned-store 。 这仍然没有启用所有现代x86 CPU所具有的其他调整选项(如优化比较和分支的宏融合)(除了低功率的),但gcc的tune = generic不能启用。 ( https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78855 )。


也:

我包括这些库mmintrin.h,emmintrin.h,xmmintrin.h

不要那样做。 始终只需在SIMD代码中包含immintrin.h 。 它引入了所有英特尔SSE / AVX扩展。 这就是您收到error: unknown type name '__m256'


请记住,下标矢量类型谎言__m256是非标准且不可移植的。 它们不是数组,没有理由你期望[]像数组一样工作。 从寄存器中的SIMD向量中提取第3个元素或其他内容需要shuffle指令,而不是加载。


如果你想要矢量类型的方便包装器,你可以使用operator[]来从矢量变量的元素中提取标量,那么看看Agner Fog的Vector类库 。 它是GPLed,所以如果这是一个问题,你将不得不查看其他包装库。

它可以让你做的事情

 // example from the manual for operator[] Vec4i a(10,11,12,13); int b = a[2]; // b = 12 

您可以在VCL类型上使用常规内在函数Vec8fVec8f上的透明包装器,因此您可以将其与_mm256_mul_ps一起_mm256_mul_ps

试试这个

RES = _MM_ADD_PS(VEC1,VEC2); 因为__M256_MM_ADD_PS的原型是

__m256 _MM_ADD_PS(__ m256,__ m256);

它需要两个__m256数据类型作为参数,并将它们的总和作为__m256数据返回,就像

int add(int,int);

用于初始化

vec = _MM_setr_PS(7.0,7.0,7.0,7.0,7.0,7.0,7.0,7.0)或

vec = _MM_LOAD_PS(&arr)或

vec = _MM_LOAD_PS(ptr)