【问题标题】:Unknown type name __m256 - Intel intrinsics for AVX not recognized?未知类型名称 __m256 - 无法识别 AVX 的英特尔内在函数?
【发布时间】:2016-12-04 09:01:12
【问题描述】:

我正在尝试测试一些 Intel Intrinsics,看看它们是如何工作的。所以,我创建了一个函数来为我做这件事,这就是代码:

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 我正在使用日食火星

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

【问题讨论】:

  • 您确定您的 CPU 支持 AVX 吗?你用的是哪个 CPU?
  • @DanielMargosian:即使他们的 CPU 不支持 AVX,编译器应该仍然能够编译它。 (存在交叉编译)。
  • 我的 CPU 是 Intel® Core™ i7-4700MQ CPU @ 2.40GHz × 8,它支持 SSE4.1/4.2, AVX 2.0
  • 你在使用 gcc 吗?我必须在命令行上指定 -mavx2 以“启用”它(并包括 immintrin.h)
  • C++ Intrinsic not declared 的可能重复项。该问题的答案涵盖了这两个部分:标题和-mavx

标签: c++ c intel intrinsics avx


【解决方案1】:

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

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

请注意 gcc -mavx 与默认 tune=generic 会将 256b loadu/storeu 内部函数拆分为 vmovups xmm / vinsertf128,如果您的数据实际上大部分时间都是对齐的,这很糟糕,尤其是在 Haswell 上shuffle-port 吞吐量有限。

不过,如果您的数据确实未对齐,这对 Sandybridge 和 Bulldozer 系列是有好处的。请参阅https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80568:它甚至会影响 AVX2 向量整数代码,即使所有 AVX2 CPU(可能除了 Excavator 和 Ryzen)会受到这种调整的伤害。 tune=generic 没有考虑启用了什么指令集扩展,也没有tune=generic-avx2

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


还有:

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

不要那样做。 Always just include immintrin.h in SIMD code。它引入了所有英特尔 SSE/AVX 扩展。这就是为什么你得到error: unknown type name ‘__m256’


请记住,下标向量类型位于 __m256 是非标准且不可移植的。它们不是数组,您没有理由应该期望[] 像数组一样工作。从寄存器中的 SIMD 向量中提取第三个元素或其他元素需要随机播放指令,而不是加载。


如果您想要方便的向量类型包装器,让您可以使用 operator[] 从向量变量的元素中提取标量,请查看 Agner Fog 的 Vector Class Library。它是 GPL 的,所以如果有问题,您将不得不查看其他包装库。

它可以让你做类似的事情

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

您可以在 VCL 类型上使用普通的内在函数Vec8f__m256 上的透明包装,因此您可以将它与_mm256_mul_ps 一起使用。

【讨论】:

  • “请记住,下标向量类型位于 __m256 是非标准且不可移植的。”在 GCC 中,至少它们实际上是数组,它们只是有一个特殊的注释来添加一些操作。此处的文档:gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
  • @JosephGarvin:正确,它在 gcc 和 clang 以及 ICC 之间是可移植的和安全的,假设他们继续以相同的方式在 GNU C 本机向量方面定义 __m256。但它可移植到 MSVC,它将 Intel 的内在类型定义为 float m128_f32[4]; 和其他一些成员的联合。 (请参阅Is accessing bytes of a __m128 variable via union legal?。)不幸的是,英特尔的内在 API 没有定义这一点,因此可移植元素访问需要存储/重新加载或包装库。
【解决方案2】:

试试这个

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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-21
    • 2011-02-12
    • 2014-03-01
    • 2020-12-19
    • 2011-12-29
    • 2012-02-12
    • 1970-01-01
    相关资源
    最近更新 更多