¿Por qué la CPU Intel Haswell XEON computa esporádicamente FFTs y ART?


Durante los últimos días observé un comportamiento de mi nueva estación de trabajo que no podía explicar. Haciendo un poco de investigación sobre este problema, podría haber un posible error en la arquitectura INTEL Haswell, así como en la generación actual de Skylake.

Antes de escribir sobre el posible error, permítanme darles una visión general del hardware utilizado, el código del programa y el problema en sí.

Especificación de hardware para estaciones de trabajo

  • INTEL Xeon E5-2680 V3 2500MHz 30M Cache 12Core
  • Supermicro SC745 BTQ-R1K28B-SQ
  • 4 x 32GB ECC registrado DDR4-2133 Ram
  • INTEL SSD 730 Series 480 GB
  • NVIDIA Tesla C2075
  • NVIDIA TITAN

Sistema operativo y código de programa en cuestión

Actualmente estoy ejecutando Ubuntu 15.04 64bit versión de escritorio, últimas actualizaciones y cosas kernel instalado. Además de usar esta máquina para desarrollar Kernels CUDA y cosas, recientemente probé un programa de C puro. El programa está haciendo una especie de ARTE modificado en conjuntos de datos de entrada bastante grandes. Así que el código ejecuta algunos FFTs y consume bastante tiempo para terminar el cálculo. Actualmente no puedo publicar / enlazar a ninguna fuente código ya que esta es una investigación en curso que no se puede publicar. Si no estás familiarizado con EL ARTE , solo una simple explicación de lo que hace. El ARTE es una técnica utilizada para reconstruir los datos recibidos de una máquina de tomógrafo de computadora para obtener imágenes visibles para el diagnóstico. Así que nuestra versión del código reconstruye conjuntos de datos de tamaños como 2048x2048x512. Hasta ahora, no había nada especial ni ciencia espacial. Después de algunas horas de depuración y corrección de errores, el código fue probado en los resultados de referencia y podemos confirmar que el código funciona como se supone que debe. La única biblioteca que está usando el código es standard math.h . No hay parámetros especiales de compilación, no hay material adicional de biblioteca que pueda traer problemas adicionales .

Observando el problema

El código implementa el arte usando una técnica para minimizar las proyecciones necesarias para reconstruir los datos. Así que vamos a suponer que podemos reconstruir una porción de datos que implican 25 proyecciones. El código se inicia con exactamente los mismos datos de entrada en 12 núcleos. Tenga en cuenta que el la implementación no se basa en multihilo, actualmente se lanzan 12 instancias del programa. Sé que esta no es la mejor manera de hacerlo, involucrando la gestión adecuada de subprocesos se aconseja fuertemente y esto ya está en la lista de mejoras :)

Así que cuando ejecutamos al menos dos instancias del programa (cada instancia trabajando en un segmento de datos separado), los resultados son de algunas proyecciones son erróneas de una manera aleatoria. Para tener una idea de los resultados, consulte la tabla 1. Tenga en cuenta que los datos de entrada son siempre los mismos.

Ejecutando solo una instancia del código que involucra un núcleo de la CPU, los resultados son todos correctos. Incluso realizando algunas ejecuciones que involucran un núcleo de CPU, los resultados siguen siendo correctos. Solo involucrando a al menos dos o más núcleos generan un patrón de resultados como se ve en la Tabla1.

Tabla 1: resultados aleatoriamente erróneos de la CPU Haswell XEON

Identificar el problema

Bien, esto tomó algunas horas para tener una idea de lo que realmente está yendo mal. Así que revisamos todo el código, la mayoría de esos problemas comienzan con un error de implementación menor. Pero, bueno, no (por supuesto no podemos probar la ausencia de errores ni garantizarlo). Para verificar nuestro código, utilizamos dos máquinas diferentes:

  • (Machine1) Intel Core i5 Quad-Core (Modelo de finales de 2009)
  • (Machine2) Máquina virtual que se ejecuta en CPU Intel XEON 6core SandyBridge

Sorprendentemente, tanto Machine1 como Machine2 producensiempre resultados correctos. Incluso usando todos los núcleos de CPU, los resultados siguen siendo correctos. Ni siquiera un resultado incorrecto en más de 50 tiradas en cada máquina. El código se compilaba en cada máquina de destino sin opciones de optimización ni ninguna configuración específica del compilador. Por lo tanto, la lectura de las noticias llevó a lo siguiente conclusiones:

Así que la gente de Prime95y la Comunidad Mersenneparecen ser los primeros en descubrir e identificar este error desagradable. Las publicaciones y noticias referenciadas apoyan la sospecha, que el problema solo existe bajo una gran carga de trabajo. Siguiendo mi observación, puedo confirmar este comportamiento.

La(s) pregunta (s)

  • ¿Ha observado usted / la comunidad este problema en las CPU Haswell así como en las CPU Skylake?
  • Como gcc hace por defecto la optimización AVX(2) (siempre que sea posible), desactivar esta optimización ayudaría?
  • ¿Cómo puedo compilar mi código y asegurarme de que cualquier optimización que pueda verse afectada por este error esté desactivada? Hasta ahora solo he leído sobre un problema al usar el comando AVX2 en las arquitecturas Haswell / Skylake.

Soluciones?

Bien, puedo desactivar todas las optimizaciones AVX2. Pero esto ralentiza mi código. Intel podría lanzar una actualización del BIOS a los fabricantes de placas base que modificaría el microcódigo en las CPU Intel. Como parece ser un error de hardware, esto podría volverse interesante incluso actualizando el microcódigo de la CPU. Creo que podría ser una opción válida, ya que las CPU Intel usan algunos RISC a CISC mecanismos de traducción controlados por Microcódigo.

EDITAR: Techreport.com -Errata solicita Intel para desactivar TSX en Haswell, principios Broadwell CPUs comprobará la versión de microcódigo en mi CPU.

EDIT2: A partir de ahora (19.01.2016 15:39 CET) Memtest86+ v4.20 se está ejecutando y probando la memoria. Como esto parece tomar bastante tiempo para terminar, actualizaré el post mañana con los resultados.

EDIT3: A partir de ahora (21.01.2016 09:35 CET) Memtest86+ terminó dos carreras y pasó. Ni siquiera un error de memoria. Actualizado el microcódigo de la CPU de revision=0x2d a revision=0x36. Actualmente preparando el código fuente para su publicación aquí. El problema con los resultados incorrectos consiste. Como no soy el autor del código en cuestión, tengo que verificar dos veces que no envíe el código postal que no se me permite. También estoy usando la estación de trabajo y manteniéndola.

EDIT4: (22.01.2016) (12:15 CET) Aquí está el Makefile usado para compilar el código fuente:

# 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

Y la salida 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) 
Author: semm0, 2016-01-19

2 answers

EDITAR: Problema resuelto. Tengo que gritar un gran perdón a la comunidad y un gran agradecimiento por sus sugerencias. Lo sentimos al usuario anónimo, que parece estar involucrado en el desarrollo del kernel. ¿Qué ha ocurrido? Pasamos otros 2 días depurando y jugueteando con el código del programa. No se detectaron problemas de aplicación. PERO: el código principal implica otro programa auxiliar. Este programa de ayuda calcula pesos para el algoritmo ART bajo demanda. Así que después de depurar y probar, este programa de ayuda en mal estado, cuando se ejecutan al menos 4 procesos. Así que esto NO fue un problema de Kernel / hardware, sino un problema de software (acceso a la memoria).

Lecciones aprendidas:

  1. Depure cada herramienta que esté involucrada en el proceso de cálculo.
  2. El microcódigo estaba desactualizado. SuperMicro está informado sobre esto.
  3. Ubuntu 15.04 posiblemente necesita herramientas adicionales, para que todos los núcleos de la CPU funcionen a toda velocidad. Logrado esto mediante la instalación de Ubuntu 14.04 - todos los núcleos que se ejecutan en 2,5 GHz.
  4. I necesito un poco de cerveza si alguna vez nos encontramos en una conferencia.

Así que después de tres días de pensar, probar y juguetear con la máquina, descubrí las siguientes observaciones hoy:

  1. Ubuntu 15.04 ejecuta la CPU con 420 - 650 MHz por Núcleo. Bien, pensé que esta es una opción de ahorro de energía, así que seguí varias guías para establecer la velocidad al máximo (2.50 GHz). No funcionó. Comprobado con cpufreq-utils.

  2. Los resultados seguían siendo erróneos después de varias pruebas en esta máquina. Otras máquinas (i5, i7, XEON) produjeron resultados correctos.

  3. He leído que otros usuarios experimentaron problemas con Ubuntu 15.04 y la frecuencia de la CPU. Así que decidí conectar un SSD e instalar Ubuntu 14.04. Comprobado de nuevo lo que la frecuencia de la CPU es ahora.. y mostró 2.50 GHz como lo esperaba.

  4. De nuevo comenzó el algoritmo de reconstrucción (que ahora era como 4-5 veces más rápido que en Ubuntu 15.04) y esperó los resultados. Vale. Los resultados son correctos ahora! Comprobé dos veces, inicié 9 procesos y comparé los resultados. Todavía correcto.

Así que solo puedo asumir que podría haber un problema en Ubuntu 15.04 / kernel usando Speedstep en esta CPU. CPU en 15.04 corrió todo el tiempo entre 420 - 650 MHz, mientras que la velocidad mínima de la CPU se espera que sea 1,20 GHz y la velocidad máxima de la CPU es de 3,30 GHz. Si alguien quiere el cheque, puedo ofrecer el código fuente y los datos de ejemplo que conducen a este problema.

Lo siento por sospechar esto es un error de CPU .

EDITAR: después de algunas pruebas más, el problema solo se resuelve para algunos escenarios, pero no para todos. Haré más pruebas.

 7
Author: semm0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-24 19:33:40

El Skylake-S/U prime95 erratum está en la unidad AVX (no AVX2). Se fija en microcodes 0x56 (probablemente) y 0x6a (seguro). Tal erratum en Haswell es improbable, pero posible (especialmente en Intel post-2014, donde la "validación" se convirtió en un costo no deseado en lugar de un inquilino para la calidad).

Haswell tiene erratas vinculadas a la unidad AVX, aunque es poco probable que HSE58 esté en juego (solo ralentiza la unidad AVX). Sin embargo, trate de colocar algunas instrucciones MFENCE antes de los cálculos AVX2. Si esto lo arregla, informe inmediatamente, significa que necesitamos MFENCE todo IRET en el núcleo (HSE105).

Su procesador tiene la firma 0x306f2. Asegúrese de tener la revisión de microcódigo 0x36 o posterior, este microcódigo está en el "Linux microcode update pack" de Intel desde 2015-11-06.

EDITAR: esto no era realmente una respuesta, así que debería haber hecho un comentario, en su lugar. Me disculpo. Dado que la actualización del microcódigo no fue suficiente para solucionar el problema, podría sigue siendo una errata nueva, una errata antigua, pero sin trabajar, o algo completamente diferente (como un error de código o un error de generación de código gcc).

 6
Author: anonymous,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-21 17:24:17