c++ - 这个 g++ 'illegal instruction error' 是由于用于构建 GCC 的 CPU 架构造成的吗?

标签 c++ docker gcc g++

我们有一个基于 centos 的 docker 镜像,它使用 gcc 5.4 来构建一个大型的 C++ 代码库。 docker 镜像从源代码构建和安装 gcc。由于我们的私有(private) docker 注册表中的一些数据丢失,我们不得不重建/将此 docker 镜像推送回我们的注册表,并开始发现使用此 docker 镜像的本地构建存在问题。

我们看到的错误是:

/usr/include/c++/5.4.0/limits:1601:7: internal compiler error: Illegal instruction
       max() _GLIBCXX_USE_NOEXCEPT { return __FLT_MAX__; }
       ^
0xa4f0cf crash_signal
        ../../gcc-5.4.0/gcc/toplev.c:383

我的理论是,这个错误是由于运行构建的底层 CPU 的架构造成的,因为我们是从源代码构建 GCC。

以前,我们有一个基于 Xeon E5 v3 CPU(Haswell 架构)的 CI 基础架构。这个 docker 镜像的构建最初是在其中一台 CI 机器上完成的,因此在本地 Haswell 开发箱上运行良好。我们的 CI 基础设施已经迁移到使用 Xeon Platinum CPU(Skylake 架构)。当我重建图像时,我是在我们的一个新 Skylake 盒子上这样做的。

由于我有一个较新的开发箱,我有一个基于 Broadwell 的 CPU,无法在本地重现该问题。我们的 CI 构建运行良好。本地出现此错误的用户使用的是 Haswell CPU。

我的理论合理吗?我已经要求用户在他们的 CPU 上本地构建我们的 docker 镜像并测试结果,但是有没有更通用的方法来解决这个问题?

我遇到了 this answer这让我指向了this documentation其中指出我可以通过 -march=*** 自己指定处理器架构。我的想法源于此:

  1. 在构建 GCC 时设置 -march=haswell 以防止启用较新的指令集
  2. 在为 Haswell 上不可用但 Broadwell/Skylake 上存在的指令集扩展构建 GCC 时设置 -mno-***

作为引用,lscpu 的输出具有这些 Broadwell 标志,这些标志在 Haswell 盒子上不存在(具有关联的 -mno-*** 标志):

3dnowprefetch
hle
rtm
rdseed
adx
smap
arch_capabilities

是否值得测试这些想法中的任何一个是否解决了这个问题?我希望得到一些外部输入,因为这个 docker build 的开发循环相当长,老实说,我不知道这些 -m 标志会解决问题。

另外,作为引用,下面是我们构建 gcc 的方式:

# build/install gcc
RUN tar xvf /tmp/archive/gcc-5.4.0.tar.gz && \
  mkdir gcc-build && \
  pushd gcc-build && \
  ../gcc-5.4.0/configure --prefix=/usr --enable-languages=c,c++,fortran --disable-multilib --with-gmp=/usr --with-mpfr=/usr --with-mpc=/usr && \
  make -j32 && \
  popd && \
  yum remove -y gcc gcc-c++ gcc-gfortran && \
  pushd gcc-build && \
  make install && \
  popd && \
  rm -rf gcc-build gcc-5.4.0

最佳答案

如维基百科 (https://en.wikipedia.org/wiki/List_of_Intel_CPU_microarchitectures) 所示,Skylake 位于 Broadwell 之后,它本身位于 Haswell 之后。

因此,在 Skylake 上构建的此类构建可能无法在较旧的 CPU 上运行,因此您应该始终将 -march=haswell 添加到您的默认构建中,以生成必须在 Haswell 及更高版本上运行的二进制文件。

使用 -march 为您的最小平台调整架构,因为您知道在启用额外的指令集时可能会有数值差异。

您还可以使用 -mtune 指定您将优化代码的目标(意味着在此平台上,代码应该更快)。您可以混合使用两者,只要 march 低于 mtune

关于c++ - 这个 g++ 'illegal instruction error' 是由于用于构建 GCC 的 CPU 架构造成的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53563791/

相关文章:

C++多维数据处理

javascript - 将类似 JavaScript 的结构编译为静态、快速的 C++ 的最佳方法是什么?

c++ - CTreeCtrl 禁用拖放特定节点

c++ - 运行时链接程序问题: “error while loading shared libraries”

docker - 我如何在 minimesos 中使用马拉松启动 kafka 调度程序?

linux - Fedora 21下ARM-GCC编译报错

tomcat - 谁能帮我为我的 tomcat 副本创建 Dockerfile?

python - Hadoop Docker容器只能复制到0个节点,而不能复制到minReplication(= 1)

c - 使用 vector 扩展时让 GCC 生成 PTEST 指令

linux - 请求 makefile 编写技巧