¿Por qué mi CPU no puede mantener el máximo rendimiento en HPC?

He desarrollado unalto rendimiento Rutina de factorización de Cholesky, que debería tener un rendimiento máximo de alrededor de 10.5 GFLOP en una sola CPU (sin hyperthreading). Pero hay un fenómeno que no entiendo cuando pruebo su rendimiento. En mi experimento, medí el rendimiento al aumentar la dimensión de la matriz N, de 250 a 10000.

En mi algoritmo he aplicado el almacenamiento en caché (con factor de bloqueo sintonizado), y siempre se accede a los datos con paso de unidad durante el cálculo, por lo que el rendimiento del caché es óptimo; Se eliminan el TLB y el problema de paginación;Tengo 8 GB de RAM disponible, y la huella de memoria máxima durante el experimento es inferior a 800 MB, por lo que no se produce ningún intercambio;Durante el experimento, no se ejecuta ningún proceso que requiera recursos como el navegador web al mismo tiempo. Solo se está ejecutando un proceso en segundo plano realmente barato para registrar la frecuencia de la CPU y los datos de temperatura de la CPU cada 2 segundos.

Esperaría que el rendimiento (en GFLOPs) se mantenga en alrededor de 10.5 para cualquier N que esté probando. Pero se observa una caída significativa del rendimiento en la mitad del experimento, como se muestra en la primera figura.

La frecuencia de la CPU y la temperatura de la CPU se ven en la segunda y tercera figura. El experimento termina en 400s. La temperatura estaba en 51 grados cuando comenzó el experimento, y rápidamente aumentó a 72 grados cuando la CPU se ocupó. Después de eso, creció lentamente al más alto a 78 grados. La frecuencia de la CPU es básicamente estable y no disminuyó cuando la temperatura subió.

Entonces, mi pregunta es:

Como la frecuencia de la CPU no disminuyó, ¿por qué sufre el rendimiento?¿Cómo afecta exactamente la temperatura al rendimiento de la CPU? ¿El incremento de 72 grados a 78 grados realmente empeora las cosas?

Información de la CPU

System: Ubuntu 14.04 LTS
Laptop model: Lenovo-YOGA-3-Pro-1370
Processor: Intel Core M-5Y71 CPU @ 1.20 GHz * 2

Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                4
On-line CPU(s) list:   0,1
Off-line CPU(s) list:  2,3
Thread(s) per core:    1
Core(s) per socket:    2
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 61
Stepping:              4
CPU MHz:               1474.484
BogoMIPS:              2799.91
Virtualisation:        VT-x
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              4096K
NUMA node0 CPU(s):     0,1

CPU 0, 1
driver: intel_pstate
CPUs which run at the same hardware frequency: 0, 1
CPUs which need to have their frequency coordinated by software: 0, 1
maximum transition latency: 0.97 ms.
hardware limits: 500 MHz - 2.90 GHz
available cpufreq governors: performance, powersave
current policy: frequency should be within 500 MHz and 2.90 GHz.
                The governor "performance" may decide which speed to use
                within this range.
current CPU frequency is 1.40 GHz.
boost state support:
  Supported: yes
  Active: yes

actualización 1 (experimento de control)

En mi experimento original, la CPU se mantiene ocupada trabajando de N = 250 a N = 10000. Muchas personas (principalmente aquellas que vieron esta publicación antes de volver a editar) sospecharon que el sobrecalentamiento de la CPU es la razón principal del impacto en el rendimiento. Luego volví e instalélm-sensors paquete de Linux para rastrear dicha información, y de hecho, la temperatura de la CPU aumentó.

Pero para completar la imagen, hice otro experimento de control. Esta vez, le doy a la CPU un tiempo de enfriamiento entre cada N. Esto se logra pidiéndole al programa que pause durante unos segundos al comienzo de la iteración del bucle a través de N.

para N entre 250 y 2500, el tiempo de enfriamiento es 5s;para N entre 2750 y 5000, el tiempo de enfriamiento es de 20 s;para N entre 5250 y 7500, el tiempo de enfriamiento es de 40 s;finalmente para N entre 7750 y 10000, el tiempo de enfriamiento es de 60 s.

Tenga en cuenta que el tiempo de enfriamiento es mucho mayor que el tiempo dedicado a la computación. Para N = 10000, solo se necesitan 30 segundos para la factorización de Cholesky al máximo rendimiento, pero solicito un tiempo de enfriamiento de 60 segundos.

Este es ciertamente unmuy poco interesante configuración en informática de alto rendimiento: queremos que nuestra máquina funcione todo el tiempo al máximo rendimiento, hasta que se complete una tarea muy grande. Entonces este tipo de detención no tiene sentido. Pero ayuda a conocer mejor el efecto de la temperatura en el rendimiento.

Esta vez, vemos que se alcanza un rendimiento máximo para todos los N, ¡tal como lo respalda la teoría! La característica periódica de la frecuencia y temperatura de la CPU es el resultado del enfriamiento y el aumento. La temperatura todavía tiene una tendencia al alza, simplemente porque a medida que aumenta N, la carga de trabajo aumenta. Esto también justifica más tiempo de enfriamiento para un enfriamiento suficiente, como lo he hecho.

El logro del rendimiento máximo parece descartar todos los efectos que no sean la temperatura. Pero esto es realmente molesto. Básicamente dice que la computadora se cansará en HPC, por lo que no podemos obtener el aumento de rendimiento esperado. Entonces, ¿cuál es el punto de desarrollar el algoritmo HPC?

OK, aquí está el nuevo conjunto de tramas:

No sé por qué no pude subir la sexta figura. SO simplemente no me permite enviar la edición al agregar la sexta figura. Así que lo siento, no puedo adjuntar la cifra de la frecuencia de la CPU.

actualización 2 (cómo mido la frecuencia y temperatura de la CPU)

Gracias a Zboson por agregar la etiqueta x86. El seguimientobash los comandos son lo que usé para medir:

while true
do 
  cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq >> cpu0_freq.txt  ## parameter "freq0"
  cat sys/devices/system/cpu/cpu1/cpufreq/scaling_cur_freq >> cpu1_freq.txt  ## parameter "freq1"
  sensors | grep "Core 0" >> cpu0_temp.txt  ## parameter "temp0"
  sensors | grep "Core 1" >> cpu1_temp.txt  ## parameter "temp1"
  sleep 2
done

Como no fijé el cálculo a 1 núcleo, el sistema operativo utilizará alternativamente dos núcleos diferentes. Tiene más sentido tomar

freq[i] <- max (freq0[i], freq1[i])
temp[i] <- max (temp0[i], temp1[i])

como la medida general

Respuestas a la pregunta(3)

Su respuesta a la pregunta