我们有一个基于映像的图像,它使用GCC 5.4构建一个大型C++代码库。docker映像从源代码构建并安装gcc。由于我们的私有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的。
以前,我们有一个基于xeone5v3cpu(haswell架构)的ci基础设施。这个Docker图像的构建最初是在其中一台CI机器上完成的,因此在本地的Haswell开发箱上运行良好。我们的CI基础设施已经迁移到使用Xeon Platinum CPU(Skylake架构)。当我重建图像时,我在一个新的Skylake盒子上做了。
由于我有一个新的开发框,我有一个基于Broadwell的CPU,无法在本地重现问题。我们的ci构建运行得非常好。在本地获取此错误的用户具有Haswell CPU。
我的理论正确吗?
我已经要求用户在他们的CPU上本地构建Docker映像并测试结果,但是有没有更通用的方法来解决这个问题呢?
我遇到了
this answer
让我直指
this documentation
哪些状态我可以通过
-march=***
. 我的想法是:
-
集合
-march=haswell
在构建gcc以防止启用较新的指令集时
-
集合
-mno-***
为haswell上不可用但存在于broadwell/skylake上的指令集扩展构建gcc时。
作为参考,输出
lscpu
有没有哈斯韦尔盒子上没有的布罗德韦尔旗
- MnO-**
标志):
3dnowprefetch
hle
rtm
rdseed
adx
smap
arch_capabilities
如果这些想法中的任何一个解决了这个问题,是否值得测试?我希望得到一些外部输入,因为这个docker构建的开发循环相当长,我真的不知道这些
-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