【问题标题】:gcc target for AVX2 disabling SSE instruction set用于 AVX2 禁用 SSE 指令集的 gcc 目标
【发布时间】:2018-06-23 16:49:40
【问题描述】:

我们有一个我们想用 AVX2 编译的翻译单元(只有那个): 它预先告诉 GCC,文件中的第一行:

#pragma GCC target "arch=core-avx2,tune=core-avx2"

这曾经与 GCC 4.8 和 4.9 一起工作,但从 6 开始(也尝试了 7 和 8)我们收到此警告(我们将其视为错误):

error: SSE instruction set disabled, using 387 arithmetics

在第一个函数返回一个浮点数。我试图像这样启用回 SSE 4.2(以及 avx 和 avx2)

#pragma GCC target "sse4.2,arch=core-avx2,tune=core-avx2"

但这还不够,错误仍然存​​在。

编辑:

相关编译器标志,我们将 AVX 用于大多数东西:

-mfpmath=sse,387 -march=corei7-avx -mtune=corei7-avx

EDIT2:最小样本:

#pragma GCC target "arch=core-avx2,tune=core-avx2"

#include <immintrin.h>
#include <math.h>

static inline float
lg1pf( float x ) {
    return log1pf(x)*1.44269504088896338700465f;
}

int main()
{
  log1pf(2.0f);
}

这样编译的:

gcc -o test test.c -O2 -Wall -Werror -pedantic -std=c99 -mfpmath=sse,387 -march=corei7-avx -mtune=corei7-avx

In file included from /home/xxx/gcc-7.1.0/lib/gcc/x86_64-pc-linux-gnu/7.1.0/include/immintrin.h:45:0,
                 from test.c:3:
/home/xxx/gcc-7.1.0/lib/gcc/x86_64-pc-linux-gnu/7.1.0/include/avx512fintrin.h: In function ‘_mm_add_round_sd’:
/home/xxx/gcc-7.1.0/lib/gcc/x86_64-pc-linux-gnu/7.1.0/include/avx512fintrin.h:1412:1: error: SSE register return with SSE disabled
 {
 ^

GCC 详细信息(虽然我没有用于编译它的标志) gcc --版本 海合会 (GCC) 7.1.0 版权所有 (C) 2017 Free Software Foundation, Inc. 这是免费软件;查看复制条件的来源。没有 保修单;甚至不考虑适销性或特定用途的适用性。

可能的解决方案

#pragma GCC target "avx2"

为我工作,无需对代码进行其他更改。 将属性应用于单个函数也不起作用:

相关问题:

__attribute__((__target__("arch=broadwell")))  // does not compile
__m256 use_avx(__m256 a) { return _mm256_add_ps(a,a); }

__attribute__((__target__("avx2,arch=broadwell"))) // does not compile
__m256 use_avx(__m256 a) { return _mm256_add_ps(a,a); }

__attribute__((__target__("avx2"))) // compiles
__m256 use_avx(__m256 a) { return _mm256_add_ps(a,a); }

【问题讨论】:

  • 你能显示整个 GCC 命令行吗?真的,您应该生成一个minimal reproducible example。有没有机会-mno-mmx -mno-sse 偷偷溜进去?
  • 提取总是有点困难......幸运的是,在较小的上下文中实际上很容易重现。
  • 你试过用-march=haswell代替奇怪/模糊的corei7-avx吗? (顺便说一句,-march 暗示 -mtune,如果你想以不同方式设置它,你只需要一个单独的-mtune。例如-march=sandybridge -mtune=haswell
  • 我确实尝试过 haswell 和其他架构名称。我会根据建议修改makefile。

标签: c gcc avx2


【解决方案1】:

这看起来像一个错误。 #pragma GCC target#include &lt;immintrin.h&gt; 之前以某种方式破坏了标题,IDK 为什么。即使在命令行上使用-march=haswell 启用了 AVX2,#pragma 似乎也会破坏此后定义的任何内在函数的内联。

您可以在标头之后使用#pragma ,但随后使用未在命令行上启用的内部函数会失败。

即使是像#pragma GCC target "arch=haswell" 这样更现代的目标名称也会导致错误,所以并不是像corei7-avx 这样的旧目标名称一般都被破坏了。他们仍然在命令行上工作。如果您想为整个文件启用某些功能,标准方法是使用编译器选项和 not 编译指示。

不过,GCC 确实声称使用编译指示或__attribute__ 在每个功能的基础上支持目标选项。 https://gcc.gnu.org/onlinedocs/gcc/Function-Specific-Option-Pragmas.html.


据我所知,这是 (Godbolt compiler explorer with gcc8.1)。 Clang 不受影响,因为它忽略了#pragma GCC target。 (这意味着#pragma 不是很便携;您可能希望您的代码与任何 GNU C 编译器一起工作,而不仅仅是 gcc 本身。)

 // breaks gcc when before immintrin.h
 // #pragma GCC target "arch=haswell"

#include <immintrin.h>
#include <math.h>

//#pragma GCC target "arch=core-avx2,tune=core-avx2"
#pragma GCC target "arch=haswell"

//static inline 
float
lg1pf( float x ) {
    return log1pf(x)*1.44269504088896338700465f;
}

// can accept / return wide vectors
__m128 nop(__m128 a) { return a; }
__m256 require_avx(__m256 a) { return a; }
// but error on using intrinsics if #include happened without target options
//__m256 use_avx(__m256 a) { return _mm256_add_ps(a,a); }

// this works, though, because AVX is enabled at this point
// presumably so would  __builtin_ia32_whatever
// Without `arch=haswell`, this breaks, so we know the pragma "worked"
__m256 use_native_vec(__m256 a) { return a+a; }

【讨论】:

  • 我非常清楚the standard way is to use compiler options and not pragmas,尽管我需要在更改任何内容之前了解正在发生的事情。
  • 这确实解决了上面的简单用例,不幸的是它对于更大的代码库来说还不够好。我想看看能不能再做一个。
  • @J.N.:这个答案的重点是显示该错误会影响什么以及它不会影响什么。我并不是说“命令行选项对每个人都足够好”,尽管如果您分解文件并且构建系统可以处理它,命令行选项实际上应该能够完成所有代码生成(尤其是如果您使用链接时优化,但具有不同目标选项的函数不能内联。)
  • 我没有成功地制作一个小样本来重现后续问题,尽管切换到“avx2”工作正常。
猜你喜欢
  • 1970-01-01
  • 2012-02-27
  • 2020-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-17
  • 2010-10-09
相关资源
最近更新 更多