为什么Intel Haswell XEON CPU偶尔会错误地计算FFT和ART?

sem*_*mm0 37 processor intel cpu-architecture avx2

在最后几天,我观察到我的新工作站的行为,我无法解释.对此问题进行一些研究,INTEL Haswell架构以及当前的Skylake Generation 可能存在一个错误.

在编写可能的错误之前,让我先概述一下使用的硬件,程序代码和问题本身.

工作站硬件规范

  • 英特尔至强E5-2680 V3 2500MHz 30M高速缓存12核心
  • Supermicro SC745 BTQ -R1K28B-SQ
  • 4 x 32GB ECC注册DDR4-2133 Ram
  • 英特尔固态硬盘730系列480 GB
  • NVIDIA Tesla C2075
  • NVIDIA TITAN

有问题的操作系统和程序代码

我目前正在运行Ubuntu 15.04 64位桌面版,安装最新更新和内核.除了使用这台机器开发CUDA内核和东西,我最近测试了一个纯C程序.该程序正在对相当大的输入数据集进行改进的ART.因此代码执行一些FFT并耗费相当长的时间来完成计算.我目前无法发布/链接到任何源代码,因为这是正在进行的无法发布的研究.如果您不熟悉ART,只需简单解释它的作用.ART是一种用于重建从计算机断层摄影机接收的数据以获得用于诊断的可见图像的技术.因此,我们的代码版本重建了大小为2048x2048x512的数据集.到目前为止,没有什么特别的,也没有涉及火箭科学.经过几个小时的调试和修复错误后,代码在参考结果上进行了测试,我们可以确认代码是否正常工作.代码使用的唯一库是标准的math.h.没有特殊的编译参数,没有额外的库可能带来额外的问题.

观察问题

该代码使用一种技术来实现ART,以最小化重建数据所需的投影.因此,我们假设我们可以重建一个涉及25个投影的数据片.代码以12个内核上完全相同的输入数据启动.请注意,实现不是基于多线程,目前启动了12个程序实例.我知道这不是最好的方法,涉及正确的线程管理是强烈建议,这已经在改进列表:)

因此,当我们运行至少两个程序实例(每个实例在一个单独的数据切片上工作)时,结果是一些预测是随机的错误.为了让您了解结果,请参阅表1.请注意,输入数据始终相同.

只运行一个涉及CPU核心的代码实例,结果都是正确的.即使执行一些涉及一个CPU内核的运行,结果仍然是正确的.仅涉及至少两个或更多核心会生成结果模式,如表1所示.

表1:Haswell XEON CPU的随机错误结果

找出问题所在

好吧,花了相当长的时间来了解究竟出了什么问题.所以我们完成了整个代码,大多数问题都是以一个小的实现错误开始的.但是,嗯,没有(当然我们不能证明没有错误也不能保证它).为验证我们的代码,我们使用了两台不同的机器:

  • (Machine1)英特尔酷睿i5四核(2009年末推出)
  • (Machine2)在Intel XEON 6core SandyBridge CPU上运行的虚拟机

出人意料的是,这两个MACHINE1和机器2产生总是正确的结果.即使使用所有CPU核心,结果仍然是正确的.每台机器上超过50次运行甚至没有错误的结果.代码是在没有优化选项或任何特定编译器设置的每台目标机器上编译的.因此,阅读新闻导致以下发现:

因此,在Prime95Mersenne社区的人们 似乎是第一批发现和识别这个讨厌的bug的人.引用的帖子和新闻支持怀疑,这个问题只存在于繁重的工作量下.根据我的观察,我可以确认这种行为.

问题

  • 您/社区是否在Haswell CPU以及Skylake CPU上发现了这个问题?
  • 正如gcc根据默认的AVX(2)优化(尽可能),关闭此优化会有帮助吗?
  • 如何编译我的代码并确保关闭可能受此错误影响的任何优化?到目前为止,我只阅读了使用Haswell/Skylake架构中的AVX2命令集的问题.

解决方案?

好的,我可以关闭所有AVX2优化.但这会减慢我的代码速度.英特尔可能会向主板制造商发布BIOS更新,以更新英特尔CPU中的微码.由于它似乎是一个硬件错误,即使更新CPU微码也可能会变得有趣.我认为这可能是一个有效的选择,因为Intel CPU使用一些由Microcode控制的RISC到CISC转换机制.

编辑:Techreport.com - 勘误表提示英特尔在Haswell中禁用TSX,早期Broadwell CPU将检查我的CPU中的微码版本.

编辑2:截至目前(19.01.2016 15:39 CET)Memtest86 + v4.20正在运行并测试内存.由于这似乎需要相当长的一段时间才能完成,我明天会用结果更新帖子.

EDIT3:截至目前(2016年1月21日09:35 CET)Memtest86 +完成了两次运行并通过了.甚至没有一个内存错误.从更新CPU的微码revision=0x2drevision=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
Run Code Online (Sandbox Code Playgroud)

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) 
Run Code Online (Sandbox Code Playgroud)

sem*_*mm0 8

编辑:问题解决了.我必须向社区大声抱歉,并非常感谢您的提示.很抱歉用户匿名,他似乎参与了内核开发.发生了什么?我们花了两天时间调试和摆弄程序代码.没有发现任何实施问题.但是:主要代码涉及另一个帮助程序.该帮助程序根据需要计算ART算法的权重.因此,在调试和测试之后,当运行至少4个进程时,这个帮助程序搞砸了.所以这不是内核/硬件问题,而是软件(内存访问)问题.

得到教训:

  1. 调试计算过程中涉及的每个工具.
  2. 微代码已经过时了.SuperMicro了解这一点.
  3. Ubuntu 15.04可能需要额外的工具,以便CPU的所有内核全速运行.通过安装Ubuntu 14.04实现了这一目标 - 所有核心都运行在2.5GHz.
  4. 如果我们在会议上见面,我需要喝点啤酒.

因此,经过三天思考,测试和摆弄机器,我今天发现了以下观察:

  1. Ubuntu 15.04以每个内核420 - 650 MHz运行CPU.好吧我认为这是一个节能选项,所以我按照各种指南将速度设置为最大值(2.50 GHz).它没用.检查cpufreq-utils.

  2. 在这台机器上进行了几次测试后,结果仍然是错 其他(i5,i7,XEON)机器产生了正确的结果.

  3. 我读到其他用户遇到了Ubuntu 15.04和CPU频率问题.所以我决定插入一个SSD并安装Ubuntu 14.04.再次检查现在的CPU频率是什么......它显示了我预期的2.50 GHz.

  4. 再次启动重建算法(现在比Ubuntu 15.04快4-5倍)并等待结果.好的.结果现在正确!我仔细检查,启动了9个流程并比较了结果.还是正确的.

所以我只能假设在这个CPU中使用Speedstep的Ubuntu 15.04 /内核可能存在问题.15.04中的CPU始终在420 - 650 MHz之间运行,而最小CPU速度预计为1,20 GHz,最大CPU速度为3,30 GHz.如果有人想要检查,我可以提供导致此问题的源代码和示例数据.

很抱歉怀疑这是一个CPU 错误.

编辑:经过一些更多的测试,问题只在某些情况下解决,但尚未解决.我会做更多测试.

  • 您是否尝试使用可用的编译器选项进行编译?喜欢`-O3 -march = native`?这应该产生另一个2到10倍的加速因子,这取决于内存带宽是否是瓶颈,以及你的代码与AVX/AVX2的自动监控程度.用"-O0"进行数字运算是愚蠢的,除非这是你能够重现问题的唯一方法.另请注意,Ubuntu 15.10自2015/10年度开始(当然).我会尝试升级到那个.(特别是因为新的编译器,比如gcc 5.2,比旧的编译器更好). (2认同)

ano*_*ous 7

Skylake-S/U prime95勘误表位于AVX(非AVX2)单元中.它固定在微码0x56(可能)和0x6a(肯定)上.Haswell中的这种错误不大可能,但可能(特别是在2014年后的英特尔,"验证"成为不受欢迎的成本,而不是质量的租户).

Haswell的勘误表链接到AVX单元,虽然HSE58是相当不可能在作怪(只减慢了AVX单位).但是,请尝试在AVX2计算之前放置一些MFENCE指令.如果这个修复它,立即报告,这意味着我们需要MFENCE内核中的所有IRET(HSE105).

您的处理器具有签名0x306f2.确保您具有微码修订版0x36或更高版本,此微代码在2015-11-06的英特尔"Linux微代码更新包"中.

编辑:这不是一个真正的答案,所以我应该做一个评论,而不是.我道歉.由于微代码更新不足以解决问题,它仍然可能是一个新的勘误,一个旧的,但没有工作的勘误,或完全不同的东西(如代码bug或gcc代码生成错误).