为什么 Intel Haswell XEON CPU 偶尔会错误计算 FFT 和 ART?
Why is Intel Haswell XEON CPU sporadically miscomputing FFTs and ART?
在过去的几天里,我观察到我无法解释的新工作站的行为。对这个问题做了一些研究,INTEL Haswell architecture 以及当前的 Skylake 一代中可能存在错误。
在写可能的BUG之前,先简单介绍一下所用的硬件、程序代码和问题本身。
工作站硬件规格
- INTEL至强E5-2680 V3 2500MHz 30M缓存12核
- 美超微 SC745 BTQ -R1K28B-SQ
- 4 x 32GB ECC 注册 DDR4-2133 内存
- 英特尔固态硬盘 730 系列 480 GB
- NVIDIA Tesla C2075
- 英伟达泰坦
有问题的操作系统和程序代码
我目前正在 运行ning Ubuntu 15.04 64 位桌面版,安装了最新更新和内核内容。除了用这台机器开发 CUDA Kernels 之类的,我最近测试了一个纯 C 程序。
该程序正在对相当大的输入数据集进行某种修改 ART。所以代码执行了一些 FFT 并消耗了相当多的时间来完成计算。我目前无法 post / link 到任何来源
代码,因为这是正在进行的研究,无法发表。如果您不熟悉 ART,请简单解释一下它的作用。 ART 是一种用于重建从计算机断层扫描仪接收到的数据以获得
用于诊断的可见图像。所以我们的代码版本重建了大小为 2048x2048x512 的数据集。到目前为止,没有什么太特别的,也没有涉及火箭科学。经过几个小时的调试和修复错误后,代码通过了测试
根据参考结果,我们可以确认代码按预期工作。代码使用的唯一库是标准库 math.h
。没有特殊的编译参数,没有可能带来额外 问题 .
的额外库内容
观察问题
该代码使用一种技术来实现 ART,以最大限度地减少重建数据所需的投影。所以让我们假设我们可以重建一个包含 25 个投影的数据切片。代码以 12 个内核上完全相同的输入数据开始。请注意,
实现不是基于多线程,目前启动了 12 个程序实例。我知道这不是最好的方法,强烈建议涉及适当的线程管理,这已经在改进列表中:)
因此,当我们 运行 至少有两个程序实例(每个实例都在一个单独的数据片上工作)时,某些预测的结果以随机方式出现错误。为了让您了解结果,请参见表 1。请注意,输入数据始终相同。
运行只有一个实例代码涉及CPU一个核心,结果全部正确。即使执行一些涉及一个 CPU 核心的 运行s,结果仍然正确。仅涉及至少两个或更多核心会生成如表 1 所示的结果模式。
确定问题
好吧,这花了好几个小时才弄清楚到底出了什么问题。所以我们检查了整个代码,大多数问题都是从一个小的实现错误开始的。但是,嗯,不(当然我们不能证明没有错误,也不能保证)。为了验证我们的代码,我们使用了两台不同的机器:
- (Machine1) Intel Core i5 四核(2009 年底的型号)
- (Machine2) 虚拟机 运行ning on Intel XEON 6core SandyBridge CPU
令人惊讶的是,Machine1 和 Machine2 都总是 产生正确的结果。即使使用所有 CPU 核,结果仍然正确。在每台机器上超过 50 运行s 甚至没有一个错误结果。代码在每台目标机器上编译,没有优化选项或任何特定的编译器设置。
因此,阅读新闻得出以下发现:
- ArsTechnika - Skylake CPU freezes during complex workload
- PcWorld - how to test your PC for the skylake bug
- Intel Community - Simple instruction for freezing a Skylake Processor
Prime95 and the Mersenne Community seem to be the first ones to discover and identify this nasty bug 那边的人。引用的 postings 和新闻支持怀疑,即问题仅在繁重的工作量下存在。根据我的观察,我可以确认这种行为。
问题
- 您/社区是否在 Haswell CPUs 以及 Skylake CPUs 上观察到这个问题?
- 由于 gcc 会根据默认的 AVX(2) 优化(只要可能),关闭此优化会有帮助吗?
- 我如何编译我的代码并确保关闭可能受此错误影响的 任何 优化?到目前为止,我只阅读了有关在 Haswell / Skylake 架构中使用 AVX2 命令集的问题。
解决方案?
好的,我可以关闭所有 AVX2 优化。但这会减慢我的代码速度。 Intel 可能会向主板制造商发布 BIOS 更新,这将修改 Intel CPUs 中的微代码。由于它似乎是一个硬件错误,因此即使更新 CPUs 微码也可能会变得有趣。我认为这可能是一个有效的选择,因为英特尔 CPUs 使用一些 RISC 到 CISC 的翻译机制,由微码控制。
编辑:Techreport.com - Errata prompts Intel to disable TSX in Haswell, early Broadwell CPUs 将检查我的 CPU 中的微码版本。
EDIT2:截至目前(19.01.2016 15:39 CET)Memtest86+ v4.20 运行正在测试内存。由于这似乎需要相当长的时间才能完成,我将在明天更新 post 结果。
EDIT3:截至目前(2016 年 1 月 21 日 09:35 CET)Memtest86+ 完成了两个 运行 并通过了。连一处记忆错误都没有。将 CPU 的微码从 revision=0x2d
更新为 revision=0x36
。目前正在准备在这里发布的源代码。结果错误的问题在于。由于我不是相关代码的作者,因此我必须仔细检查是否 post 我不允许的代码。我也在使用工作站并维护它。
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)
Skylake-S/U prime95 错误在 AVX(不是 AVX2)单元中。它固定在微码 0x56(可能)和 0x6a(肯定)上。 Haswell 中的此类错误不太可能,但有可能(特别是在 post-2014 Intel 上,其中 "validation" 成为不受欢迎的成本,而不是质量的承租人)。
Haswell 有 链接到 AVX 单元的勘误表,尽管 HSE58 不太可能起作用(它只会减慢 AVX 单元的速度)。但是,请尝试在 AVX2 计算之前放置一些 MFENCE 指令。如果这解决了问题,请立即报告,这意味着我们需要 MFENCE 内核中的所有 IRET (HSE105)。
您的处理器具有签名 0x306f2。确保您的微码版本为 0x36 或更高版本,此微码在 2015-11-06 的 Intel "Linux microcode update pack" 中。
编辑:这并不是真正的回答,所以我应该将其作为评论。我道歉。由于微代码更新不足以解决问题,它仍然可能是一个新的勘误表,一个旧的,但 unworked-around 勘误表,或者完全是其他东西(例如代码错误或 gcc 代码生成错误)。
编辑:问题已解决。我必须向社区大声说声抱歉,并非常感谢您的提示。抱歉匿名用户,他似乎参与了内核开发。发生了什么?我们又花了 2 天时间调试和摆弄程序代码。没有发现实施问题。但是:主要代码涉及另一个帮助程序。该帮助程序按需计算 ART 算法的权重。所以经过调试和测试,这个辅助程序搞砸了,当运行宁至少4个进程。所以这不是内核/硬件问题,而是软件(内存访问)问题。
经验教训:
- 调试计算过程中涉及的每个工具。
- 微码已过时。 SuperMicro 已获悉此事。
- Ubuntu 15.04 可能需要额外的工具,以便 CPU 运行 的所有内核全速运行。通过安装 Ubuntu 14.04 - 所有内核 运行ning 在 2.5GHz 下实现此目的。
- 如果我们在会议上见面,我需要喝点啤酒。
经过三天的思考、测试和摆弄机器,我今天发现了以下观察结果:
Ubuntu 15.04 运行s CPU 每核心 420 - 650 MHz。好的,我认为这是一个 Energy-saving 选项,所以我按照各种指南将速度设置为最大值 (2.50 GHz)。它没有用。用 cpufreq-utils
.
检查
在本机上测试了几次,结果还是不对。其他(i5、i7、XEON)机器产生了正确的结果。
我读到其他用户遇到了 Ubuntu 15.04 和 CPU 频率的问题。所以我决定插入SSD并安装Ubuntu 14.04。再次检查现在 CPU 的频率是多少……它显示了 2.50 GHz,正如我所期望的那样。
再次启动重建算法(现在比 Ubuntu 15.04 快 4-5 倍)并等待结果。好的。现在结果正确!我仔细检查,启动了 9 个进程并比较了结果。还是正确的。
所以我只能假设 Ubuntu 15.04 / 内核在这个 CPU 中使用 Speedstep 可能有问题。 CPU 15.04 运行 一直在 420 - 650 MHz 之间,而最小 CPU 速度预计为 1,20 GHz,最大 CPU 速度为 3, 30 GHz。如果有人想要检查,我可以提供导致这个问题的源代码和示例数据。
抱歉怀疑这是一个 CPU bug。
编辑:经过更多测试后,问题仅在某些情况下得到解决,但尚未解决所有情况。我会做更多的测试。
在过去的几天里,我观察到我无法解释的新工作站的行为。对这个问题做了一些研究,INTEL Haswell architecture 以及当前的 Skylake 一代中可能存在错误。
在写可能的BUG之前,先简单介绍一下所用的硬件、程序代码和问题本身。
工作站硬件规格
- INTEL至强E5-2680 V3 2500MHz 30M缓存12核
- 美超微 SC745 BTQ -R1K28B-SQ
- 4 x 32GB ECC 注册 DDR4-2133 内存
- 英特尔固态硬盘 730 系列 480 GB
- NVIDIA Tesla C2075
- 英伟达泰坦
有问题的操作系统和程序代码
我目前正在 运行ning Ubuntu 15.04 64 位桌面版,安装了最新更新和内核内容。除了用这台机器开发 CUDA Kernels 之类的,我最近测试了一个纯 C 程序。
该程序正在对相当大的输入数据集进行某种修改 ART。所以代码执行了一些 FFT 并消耗了相当多的时间来完成计算。我目前无法 post / link 到任何来源
代码,因为这是正在进行的研究,无法发表。如果您不熟悉 ART,请简单解释一下它的作用。 ART 是一种用于重建从计算机断层扫描仪接收到的数据以获得
用于诊断的可见图像。所以我们的代码版本重建了大小为 2048x2048x512 的数据集。到目前为止,没有什么太特别的,也没有涉及火箭科学。经过几个小时的调试和修复错误后,代码通过了测试
根据参考结果,我们可以确认代码按预期工作。代码使用的唯一库是标准库 math.h
。没有特殊的编译参数,没有可能带来额外 问题 .
观察问题
该代码使用一种技术来实现 ART,以最大限度地减少重建数据所需的投影。所以让我们假设我们可以重建一个包含 25 个投影的数据切片。代码以 12 个内核上完全相同的输入数据开始。请注意, 实现不是基于多线程,目前启动了 12 个程序实例。我知道这不是最好的方法,强烈建议涉及适当的线程管理,这已经在改进列表中:)
因此,当我们 运行 至少有两个程序实例(每个实例都在一个单独的数据片上工作)时,某些预测的结果以随机方式出现错误。为了让您了解结果,请参见表 1。请注意,输入数据始终相同。
运行只有一个实例代码涉及CPU一个核心,结果全部正确。即使执行一些涉及一个 CPU 核心的 运行s,结果仍然正确。仅涉及至少两个或更多核心会生成如表 1 所示的结果模式。
确定问题
好吧,这花了好几个小时才弄清楚到底出了什么问题。所以我们检查了整个代码,大多数问题都是从一个小的实现错误开始的。但是,嗯,不(当然我们不能证明没有错误,也不能保证)。为了验证我们的代码,我们使用了两台不同的机器:
- (Machine1) Intel Core i5 四核(2009 年底的型号)
- (Machine2) 虚拟机 运行ning on Intel XEON 6core SandyBridge CPU
令人惊讶的是,Machine1 和 Machine2 都总是 产生正确的结果。即使使用所有 CPU 核,结果仍然正确。在每台机器上超过 50 运行s 甚至没有一个错误结果。代码在每台目标机器上编译,没有优化选项或任何特定的编译器设置。 因此,阅读新闻得出以下发现:
- ArsTechnika - Skylake CPU freezes during complex workload
- PcWorld - how to test your PC for the skylake bug
- Intel Community - Simple instruction for freezing a Skylake Processor
Prime95 and the Mersenne Community seem to be the first ones to discover and identify this nasty bug 那边的人。引用的 postings 和新闻支持怀疑,即问题仅在繁重的工作量下存在。根据我的观察,我可以确认这种行为。
问题
- 您/社区是否在 Haswell CPUs 以及 Skylake CPUs 上观察到这个问题?
- 由于 gcc 会根据默认的 AVX(2) 优化(只要可能),关闭此优化会有帮助吗?
- 我如何编译我的代码并确保关闭可能受此错误影响的 任何 优化?到目前为止,我只阅读了有关在 Haswell / Skylake 架构中使用 AVX2 命令集的问题。
解决方案?
好的,我可以关闭所有 AVX2 优化。但这会减慢我的代码速度。 Intel 可能会向主板制造商发布 BIOS 更新,这将修改 Intel CPUs 中的微代码。由于它似乎是一个硬件错误,因此即使更新 CPUs 微码也可能会变得有趣。我认为这可能是一个有效的选择,因为英特尔 CPUs 使用一些 RISC 到 CISC 的翻译机制,由微码控制。
编辑:Techreport.com - Errata prompts Intel to disable TSX in Haswell, early Broadwell CPUs 将检查我的 CPU 中的微码版本。
EDIT2:截至目前(19.01.2016 15:39 CET)Memtest86+ v4.20 运行正在测试内存。由于这似乎需要相当长的时间才能完成,我将在明天更新 post 结果。
EDIT3:截至目前(2016 年 1 月 21 日 09:35 CET)Memtest86+ 完成了两个 运行 并通过了。连一处记忆错误都没有。将 CPU 的微码从 revision=0x2d
更新为 revision=0x36
。目前正在准备在这里发布的源代码。结果错误的问题在于。由于我不是相关代码的作者,因此我必须仔细检查是否 post 我不允许的代码。我也在使用工作站并维护它。
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)
Skylake-S/U prime95 错误在 AVX(不是 AVX2)单元中。它固定在微码 0x56(可能)和 0x6a(肯定)上。 Haswell 中的此类错误不太可能,但有可能(特别是在 post-2014 Intel 上,其中 "validation" 成为不受欢迎的成本,而不是质量的承租人)。
Haswell 有 链接到 AVX 单元的勘误表,尽管 HSE58 不太可能起作用(它只会减慢 AVX 单元的速度)。但是,请尝试在 AVX2 计算之前放置一些 MFENCE 指令。如果这解决了问题,请立即报告,这意味着我们需要 MFENCE 内核中的所有 IRET (HSE105)。
您的处理器具有签名 0x306f2。确保您的微码版本为 0x36 或更高版本,此微码在 2015-11-06 的 Intel "Linux microcode update pack" 中。
编辑:这并不是真正的回答,所以我应该将其作为评论。我道歉。由于微代码更新不足以解决问题,它仍然可能是一个新的勘误表,一个旧的,但 unworked-around 勘误表,或者完全是其他东西(例如代码错误或 gcc 代码生成错误)。
编辑:问题已解决。我必须向社区大声说声抱歉,并非常感谢您的提示。抱歉匿名用户,他似乎参与了内核开发。发生了什么?我们又花了 2 天时间调试和摆弄程序代码。没有发现实施问题。但是:主要代码涉及另一个帮助程序。该帮助程序按需计算 ART 算法的权重。所以经过调试和测试,这个辅助程序搞砸了,当运行宁至少4个进程。所以这不是内核/硬件问题,而是软件(内存访问)问题。
经验教训:
- 调试计算过程中涉及的每个工具。
- 微码已过时。 SuperMicro 已获悉此事。
- Ubuntu 15.04 可能需要额外的工具,以便 CPU 运行 的所有内核全速运行。通过安装 Ubuntu 14.04 - 所有内核 运行ning 在 2.5GHz 下实现此目的。
- 如果我们在会议上见面,我需要喝点啤酒。
经过三天的思考、测试和摆弄机器,我今天发现了以下观察结果:
Ubuntu 15.04 运行s CPU 每核心 420 - 650 MHz。好的,我认为这是一个 Energy-saving 选项,所以我按照各种指南将速度设置为最大值 (2.50 GHz)。它没有用。用
cpufreq-utils
. 检查
在本机上测试了几次,结果还是不对。其他(i5、i7、XEON)机器产生了正确的结果。
我读到其他用户遇到了 Ubuntu 15.04 和 CPU 频率的问题。所以我决定插入SSD并安装Ubuntu 14.04。再次检查现在 CPU 的频率是多少……它显示了 2.50 GHz,正如我所期望的那样。
再次启动重建算法(现在比 Ubuntu 15.04 快 4-5 倍)并等待结果。好的。现在结果正确!我仔细检查,启动了 9 个进程并比较了结果。还是正确的。
所以我只能假设 Ubuntu 15.04 / 内核在这个 CPU 中使用 Speedstep 可能有问题。 CPU 15.04 运行 一直在 420 - 650 MHz 之间,而最小 CPU 速度预计为 1,20 GHz,最大 CPU 速度为 3, 30 GHz。如果有人想要检查,我可以提供导致这个问题的源代码和示例数据。
抱歉怀疑这是一个 CPU bug。
编辑:经过更多测试后,问题仅在某些情况下得到解决,但尚未解决所有情况。我会做更多的测试。