在最后几天,我观察到我无法解释的新工作站的行为。对这个问题进行一些研究,在INTEL Haswell 架构以及当前的 Skylake Generation 中可能存在一个错误。
在写可能的错误之前,让我先概述一下所使用的硬件、程序代码和问题本身。
工作站硬件规格
- INTEL 至强 E5-2680 V3 2500MHz 30M 缓存 12核
- 美超微 SC745 BTQ -R1K28B-SQ
- 4 x 32GB ECC 注册 DDR4-2133 内存
- 英特尔 SSD 730 系列 480 GB
- 英伟达特斯拉 C2075
- 英伟达泰坦
有问题的操作系统和程序代码
我目前正在运行 Ubuntu 15.04 64 位桌面版本,已安装最新更新和内核内容。除了使用这台机器开发 CUDA 内核和其他东西,我最近测试了一个纯 C 程序。该程序正在对相当大的输入数据集进行某种修改后的ART 。因此代码执行了一些 FFT 并消耗了相当长的时间来完成计算。我目前无法发布/链接到任何源代码,因为这是正在进行的研究,无法发布。如果您不熟悉ART,只是一个简单的解释它的作用。ART 是一种用于重建从计算机断层扫描仪接收到的数据以获取用于诊断的可见图像的技术。因此,我们的代码版本重构了大小为 2048x2048x512 的数据集。到目前为止,没有什么特别的,也没有涉及火箭科学。经过几个小时的调试和修复错误,代码在参考结果上进行了测试,我们可以确认代码按预期工作。代码使用的唯一库是 standard math.h
。没有特殊的编译参数,没有可能带来额外问题的额外库内容。
观察问题
该代码使用一种技术来实现 ART,以最小化重建数据所需的投影。所以让我们假设我们可以重建一个包含 25 个投影的数据切片。代码以 12 个内核上完全相同的输入数据开始。请注意,该实现不是基于多线程的,目前启动了 12 个程序实例。我知道这不是最好的方法,强烈建议涉及适当的线程管理,这已经在改进列表中:)
因此,当我们运行至少两个程序实例(每个实例都在单独的数据切片上工作)时,一些预测的结果是随机错误的。为了让您了解结果,请参见表 1。请注意,输入数据始终相同。
只运行一个涉及 CPU 一个核心的代码实例,结果都是正确的。即使执行一些涉及一个 CPU 内核的运行,结果仍然正确。仅涉及至少两个或更多内核会生成结果模式,如表 1 所示。
识别问题
好的,这花了好几个小时来了解实际出了什么问题。所以我们检查了整个代码,大部分问题都是从一个小的实现错误开始的。但是,好吧,没有(当然我们不能证明没有错误也不能保证)。为了验证我们的代码,我们使用了两台不同的机器:
- (机器 1)英特尔酷睿 i5 四核(2009 年末型号)
- (Machine2) 在 Intel XEON 6core SandyBridge CPU 上运行的虚拟机
令人惊讶的是,Machine1 和 Machine2总是产生正确的结果。即使使用所有 CPU 内核,结果仍然正确。在每台机器上运行超过 50 次,甚至没有一个错误的结果。代码在每台目标机器上编译,没有优化选项或任何特定的编译器设置。因此,阅读新闻导致以下发现:
- ArsTechnika - Skylake CPU 在复杂工作负载期间冻结
- PcWorld - 如何测试您的 PC 是否存在 skylake 错误
- 英特尔社区 - 冻结 Skylake 处理器的简单说明
因此,Prime95和Mersenne 社区的 人们似乎是第一个发现和识别这个讨厌的错误的人。引用的贴子和新闻支持了这种怀疑,即问题只存在于工作量大的情况下。根据我的观察,我可以确认这种行为。
问题
- 您/社区是否在 Haswell CPU 和 Skylake CPU 上观察到此问题?
- 由于 gcc 每个默认的 AVX(2) 优化(尽可能),关闭此优化会有所帮助吗?
- 如何编译我的代码并确保关闭可能受此错误影响的任何优化?到目前为止,我只阅读了有关在 Haswell / Skylake 架构中使用 AVX2 命令集的问题。
解决方案?
好的,我可以关闭所有 AVX2 优化。但这会减慢我的代码速度。英特尔可能会向主板制造商发布 BIOS 更新,以修改英特尔 CPU 中的微码。由于这似乎是一个硬件错误,即使通过更新 CPU 微码,这也可能会变得有趣。我认为这可能是一个有效的选择,因为英特尔 CPU 使用一些由微码控制的 RISC 到 CISC 转换机制。
编辑:Techreport.com - 勘误表提示英特尔在 Haswell 中禁用 TSX,早期的 Broadwell CPU将检查我 CPU 中的微码版本。
EDIT2:截至目前(19.01.2016 15:39 CET)Memtest86+ v4.20 正在运行并测试内存。由于这似乎需要相当长的时间才能完成,我将在明天更新帖子并提供结果。
EDIT3:截至目前(21.01.2016 09:35 CET)Memtest86+ 完成了两次运行并通过了。甚至没有一个内存错误。将 CPU 的微码从 更新revision=0x2d
为revision=0x36
。目前正在准备这里发布的源代码。错误结果的问题在于。由于我不是相关代码的作者,因此我必须仔细检查不要发布我不允许发布的代码。我也在使用工作站并对其进行维护。
EDIT4: (22.01.2016) (12:15 CET) 这是用于编译源代码的 Makefile:
# VARIABLES ==================================================================
CC = gcc
CFLAGS = --std=c99 -Wall
#LDFLAGS = -lm -lgomp -fast -s -m64
LDFLAGS = -lm
OBJ = ArtReconstruction2Min.o
# RULES AND DEPENDENCIES ====================================================
# linking all object files
all: $(OBJ)
$(CC) -o ART2Min $(OBJ) $(LDFLAGS)
# every o-file depends on the corresonding c-file, -g Option bedeutet Debugging Informationene setzen
%.o: %.c
$(CC) -c -g $< $(CFLAGS)
# MAKE CLEAN =================================================================
clean:
rm -f *.o
rm -f main
和gcc -v
输出:
gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.9.2-10ubuntu13' --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.9-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.9.2 (Ubuntu 4.9.2-10ubuntu13)