Bajo rendimiento debido a la hiperprocesamiento con OpenMP: cómo vincular subprocesos a núcleos
Estoy desarrollando un código de multiplicación de matriz densa grande. Cuando perfilo el código, a veces obtiene aproximadamente el 75% de los picos de flops de mi sistema de cuatro núcleos y otras veces obtiene aproximadamente el 36%. La eficiencia no cambia entre las ejecuciones del código. Comienza con el 75% y continúa con esa eficiencia o comienza con el 36% y continúa con esa eficiencia.
He rastreado el problema hasta el subproceso y el hecho de que configuré el número de subprocesos en cuatro en lugar de los ocho predeterminados.Cuando desactivo el hiperprocesamiento en el BIOS obtengo aproximadamente el 75% de eficiencia de manera consistente (o al menos nunca veo la caída drástica al 36%).
Antes de llamar a cualquier código paralelo que hagoomp_set_num_threads(4)
. También he intentadoexport OMP_NUM_THREADS=4
antes de ejecutar mi código, pero parece ser equivalente.
No quiero deshabilitar hyper-threading en el BIOS. Creo que necesito unir los cuatro hilos a los cuatro núcleos. He probado algunos casos diferentes deGOMP_CPU_AFFINITY
pero hasta ahora todavía tengo el problema de que la eficiencia es a veces del 36%.¿Qué es el mapeo con hyper-threading y núcleos? P.ej. ¿El hilo 0 y el hilo 1 corresponden al mismo núcleo y el hilo 2 y el hilo 3 a otro núcleo?
¿Cómo puedo vincular los subprocesos a cada núcleo sin migración de subprocesos para que no tenga que deshabilitar el hiperprocesamiento en el BIOS? Tal vez necesito considerar usarsched_setaffinity?
Algunos detalles de mi sistema actual: Linux kernel 3.13, GCC 4.8, Intel Xeon E5-1620 (cuatro núcleos físicos, ocho hiperprocesos).
Editar: Esto parece estar funcionando bien hasta ahora
export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7"
o
export GOMP_CPU_AFFINITY="0-7"
Editar: Esto también parece funcionar bien
export OMP_PROC_BIND=true
Editar:Estas opciones también funciona bien (gemm es el nombre de mi ejecutable)
numactl -C 0,1,2,3 ./gemm
y
taskset -c 0,1,2,3 ./gemm