performance - pagina - Análisis de la causa de la regresión del rendimiento con diferentes versiones del kernel.
linux last stable kernel (2)
Este cambio podría ser un posible candidato http://marc.info/?l=linux-kernel&m=138012715018064 . Digo esto libremente ya que no tengo los recursos para confirmar. Vale la pena señalar que este fue el único cambio significativo en el programador entre 3.11.10 y 3.12.6.
De todos modos, estoy muy interesado en ver los resultados finales de sus hallazgos, así que manténgannos informados.
Me he encontrado con una extraña regresión de rendimiento del kernel de Linux 3.11 a 3.12 en sistemas x86_64. El índice de referencia Radiance de Running Stock Stock en Fedora 20, 3.12 es notablemente más lento. No se cambia nada más, binario idéntico, glibc idéntico, solo arranco una versión diferente del kernel y el rendimiento cambia. El programa cronometrado, rpict, es 100% código de nivel de usuario vinculado a la CPU.
Antes de informar esto como un error, me gustaría encontrar la causa de este comportamiento. No sé mucho sobre el kernel de Linux, y el registro de cambios de 3.11 a 3.12 no me da ninguna pista.
Observé esto en dos sistemas, un Intel Haswell (i7-4771) y un AMD Richland (A8-6600K). En el sistema Haswell, el tiempo del usuario pasó de 895 segundos con 3.11 a 962 con 3.12. En Richland, de 1764 a 1844. Estos tiempos pueden repetirse en unos pocos segundos.
Hice algunos perfiles con perf, y descubrí que el IPC se redujo en la misma proporción que la desaceleración. En el sistema de Haswell, esto parece ser causado por más ramas perdidas, pero ¿por qué debería disminuir la tasa de predicción? La radiancia usa el generador de números aleatorios. ¿Podría "mejor" la aleatoriedad causar las ramas perdidas? Pero aparte de la compatibilidad con OMAP4, el RNG no tiene que parecer cambiado en 3.12.
En el sistema AMD, el rendimiento solo apunta a más ciclos de backend inactivos, pero la causa no está clara.
Sistema Haswell:
3.11.10 895s user, 3.74% branch-misses, 1.65 insns per cycle
3.12.6 962s user, 4.22% branch-misses, 1.52 insns per cycle
Sistema de Richland:
3.11.10 1764s user, 8.23% branch-misses, 0.75 insns per cycle
3.12.6 1844s user, 8.26% branch-misses, 0.72 insns per cycle
También observé una diferencia con la salida de dmesg de ambos núcleos, pero no vi nada que pudiera haber provocado una desaceleración de un programa vinculado a la CPU.
Intenté cambiar el gobernador cpufreq del valor predeterminado de ondemand a peformance pero eso no tuvo ningún efecto.
El ejecutable se compiló utilizando gcc 4.7.3 pero no utilizando las instrucciones de AVX. Parece que libm todavía usa algún AVX (por ejemplo, __ieee754_pow_fma4
) pero estas funciones son solo el 0.3% del tiempo total de ejecución.
Información adicional:
- Diff de las configuraciones de kernel
- Diferencia de las salidas dmesg en el sistema Haswell.
- diff de / proc / pid / maps - 3.11 mapea solo una región de pila; 3.12 lotes.
- Salida de estadísticas del sistema A8-6600K
- perf stats w / TLB pierde dTLB stats se ven muy diferentes!
- Salida de / usr / bin / time -v desde el sistema A8-6600K
¿Alguna idea (aparte de dividir en dos los cambios del núcleo)?
Revisemos las salidas de sus perf stat
rendimiento: http://www.chr-breitkopf.de/tmp/perf-stat.A8.txt
Kernel 3.11.10
1805057.522096 task-clock # 0.999 CPUs utilized
183,822 context-switches # 0.102 K/sec
109 cpu-migrations # 0.000 K/sec
40,451 page-faults # 0.022 K/sec
7,523,630,814,458 cycles # 4.168 GHz [83.31%]
628,027,409,355 stalled-cycles-frontend # 8.35% frontend cycles idle [83.34%]
2,688,621,128,444 stalled-cycles-backend # 35.74% backend cycles idle [33.35%]
5,607,337,995,118 instructions # 0.75 insns per cycle
# 0.48 stalled cycles per insn [50.01%]
825,679,208,404 branches # 457.425 M/sec [66.67%]
67,984,693,354 branch-misses # 8.23% of all branches [83.33%]
1806.804220050 seconds time elapsed
Kernel 3.12.6
1875709.455321 task-clock # 0.999 CPUs utilized
192,425 context-switches # 0.103 K/sec
133 cpu-migrations # 0.000 K/sec
40,356 page-faults # 0.022 K/sec
7,822,017,368,073 cycles # 4.170 GHz [83.31%]
634,535,174,769 stalled-cycles-frontend # 8.11% frontend cycles idle [83.34%]
2,949,638,742,734 stalled-cycles-backend # 37.71% backend cycles idle [33.35%]
5,607,926,276,713 instructions # 0.72 insns per cycle
# 0.53 stalled cycles per insn [50.01%]
825,760,510,232 branches # 440.239 M/sec [66.67%]
68,205,868,246 branch-misses # 8.26% of all branches [83.33%]
1877.263511002 seconds time elapsed
Hay casi 300 Gcycles más para 3.12.6 en el campo "ciclos"; y solo 6,5 Gcycles fueron puestos de la parte frontal y 261 Gcycles se detuvieron en el backend. Solo tiene 0,2 G de fallas adicionales en la sucursal (cada una cuesta aproximadamente 20 ciclos, según optim.manual página 597; por lo tanto, 4Gcycles), por lo que creo que sus problemas de rendimiento están relacionados con problemas del subsistema de memoria (evento más realista en el backend, que puede ser influenciado por el núcleo). Las diferencias entre la frecuencia de las páginas y el número de migraciones son bajos, y creo que no demorarán la prueba directamente (pero las migraciones pueden mover el programa al peor lugar).
Debería profundizar en los contadores de perf
para encontrar el tipo exacto de problema (será más fácil si tiene ejecuciones de prueba más cortas). El manual de Intel http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf le ayudará. Consulte la página 587 (B.3.2) para ver la jerarquía general de eventos (las paradas FE y BE también están aquí), B.3.2.1-B.3.2.3 para obtener información sobre las paradas de backend y cómo comenzar a excavar (verifica eventos de caché, etc.) ) y por debajo.
¿Cómo puede el kernel influir en el subsistema de memoria? Puede configurar diferentes mapas virtuales a físicos (no es su caso), o puede mover el proceso más lejos de los datos. No tiene la máquina NUMA, pero Haswell no es la UMA exacta; hay un bus de anillo y algunos núcleos están más cerca del controlador de memoria o de algunas partes de la LLC compartida (caché de último nivel). Puede probar su programa con la utilidad de conjunto de taskset
, limitándola a algún núcleo: el núcleo no lo moverá a otro núcleo.
ACTUALIZACIÓN: Después de revisar sus nuevas estadísticas de perfección de A8, vemos que hay más DLTB: faltas para 3.12.6. Con los cambios en / proc / pid / maps (muchas secciones cortas de [heap]
lugar de single [heap]
, todavía no hay información exacta por qué), creo que puede haber diferencias en la página de acceso transparente (THP; con 2M hugepages hay menos Las entradas de TLB necesarias para la misma cantidad de memoria y menos errores de tlb), por ejemplo, en 3.12 no se pueden aplicar debido a las secciones de pila cortas.
Puede consultar su /proc/PID/smaps
para AnonHugePages
/proc/PID/smaps
de AnonHugePages
y /proc/vmstat
para ver los resultados de thp *. Los valores se documentan aquí kernel.org/doc/Documentation/vm/transhuge.txt
@osgx ¡Has encontrado la causa! Después de echo nunca> / sys / kernel / mm / transparent_hugepage / enabled, 3.11.10 toma hasta 3.12.6!
¡Buenas noticias!
Se agradecería información adicional sobre cómo deshabilitar la asignación aleatoria y sobre dónde informar esto como un error (una regresión de rendimiento del 7% es bastante grave)
Me equivoqué, este efecto de la sección de múltiples pilas no es la aleatorización brk (que cambia solo al principio de la pila). Esto es un fallo de la fusión de VMA en do_brk
; no sé por qué, pero algunos cambios para VM_SOFTDIRTY se vieron en mm
entre 3.11.10 - 3.12.6.
ACTUALIZACIÓN2: Posible causa de no fusionar VMA:
http://lxr.missinglinkelectronics.com/linux+v3.11/mm/mmap.c#L2580 do_brk en 3.11
http://lxr.missinglinkelectronics.com/linux+v3.11/mm/mmap.c#L2577 do_brk en 3.12
3.12 acaba de agregarse al final de do_brk
2663 vma->vm_flags |= VM_SOFTDIRTY;
2664 return addr;
Y poco encima tenemos
2635 /* Can we just expand an old private anonymous mapping? */
2636 vma = vma_merge(mm, prev, addr, addr + len, flags,
2637 NULL, NULL, pgoff, NULL);
y dentro de vma_merge
hay una prueba para vm_flags
http://lxr.missinglinkelectronics.com/linux+v3.11/mm/mmap.c#L994 3.11
http://lxr.missinglinkelectronics.com/linux+v3.12/mm/mmap.c#L994 3.12
1004 /*
1005 * We later require that vma->vm_flags == vm_flags,
1006 * so this tests vma->vm_flags & VM_SPECIAL, too.
1007 */
vma_merge -> can_vma_merge_before -> is_mergeable_vma ...
898 if (vma->vm_flags ^ vm_flags)
899 return 0;
Pero al momento de la verificación, el nuevo vma no está marcado como VM_SOFTDIRTY, mientras que el antiguo ya está marcado.