CPU de alto kernel cuando se ejecutan varios progtwigs de python

Desarrollé un progtwig de python que hace cálculos numéricos pesados. Lo ejecuto en una máquina Linux con 32 CPU Xeon, 64 GB de RAM y Ubuntu 14.04 de 64 bits. Lance múltiples instancias de Python con diferentes parámetros de modelo en paralelo para usar múltiples procesos sin tener que preocuparme por el locking global del intérprete (GIL). Cuando superviso la utilización de la CPU utilizando htop , veo que todos los núcleos se utilizan, sin embargo, la mayoría de las veces por el núcleo. Generalmente, el tiempo del kernel es más del doble del tiempo del usuario. Me temo que hay muchos gastos generales en el nivel del sistema, pero no puedo encontrar la causa de esto.

¿Cómo se podría reducir el uso elevado de CPU del kernel?

Aquí hay algunas observaciones que hice:

  • Este efecto aparece independientemente de si ejecuto 10 trabajos o 50. Si hay menos trabajos que núcleos, no se usan todos los núcleos, pero los que se usan aún tienen un alto uso de CPU por parte del kernel
  • Implementé el bucle interno usando numba , pero el problema no está relacionado con esto, ya que eliminar la parte numba no resuelve el problema
  • También pensé que podría estar relacionado con el uso de python2 similar al problema mencionado en esta pregunta SO, pero el cambio de python2 a python3 no cambió mucho
  • Medí el número total de cambios de contexto realizados por el sistema operativo, que es de aproximadamente 10000 por segundo. No estoy seguro de si este es un número grande
  • Intenté boost los intervalos de tiempo de python configurando sys.setcheckinterval(10000) (para python2) y sys.setswitchinterval(10) (para python3) pero nada de esto ayudó
  • Intenté influir en el progtwigdor de tareas ejecutando schedtool -B PID pero esto no ayudó

Edición: Aquí hay una captura de pantalla de htop : introduzca la descripción de la imagen aquí

También ejecuté el perf record -a -g y este es el informe por perf report -g graph :

 Samples: 1M of event 'cycles', Event count (approx.): 1114297095227 - 95.25% python3 [kernel.kallsyms] [k] _raw_spin_lock_irqsave ◆ - _raw_spin_lock_irqsave ▒ - 95.01% extract_buf ▒ extract_entropy_user ▒ urandom_read ▒ vfs_read ▒ sys_read ▒ system_call_fastpath ▒ __GI___libc_read ▒ - 2.06% python3 [kernel.kallsyms] [k] sha_transform ▒ - sha_transform ▒ - 2.06% extract_buf ▒ extract_entropy_user ▒ urandom_read ▒ vfs_read ▒ sys_read ▒ system_call_fastpath ▒ __GI___libc_read ▒ - 0.74% python3 [kernel.kallsyms] [k] _mix_pool_bytes ▒ - _mix_pool_bytes ▒ - 0.74% __mix_pool_bytes ▒ extract_buf ▒ extract_entropy_user ▒ urandom_read ▒ vfs_read ▒ sys_read ▒ system_call_fastpath ▒ __GI___libc_read ▒ 0.44% python3 [kernel.kallsyms] [k] extract_buf ▒ 0.15% python3 python3.4 [.] 0x000000000004b055 ▒ 0.10% python3 [kernel.kallsyms] [k] memset ▒ 0.09% python3 [kernel.kallsyms] [k] copy_user_generic_string ▒ 0.07% python3 multiarray.cpython-34m-x86_64-linux-gnu.so [.] 0x00000000000b4134 ▒ 0.06% python3 [kernel.kallsyms] [k] _raw_spin_unlock_irqrest▒ 0.06% python3 python3.4 [.] PyEval_EvalFrameEx 

Parece que la mayor parte del tiempo se invierte en llamar a _raw_spin_lock_irqsave . Aunque no tengo idea de lo que esto significa.

Si el problema existe en el kernel, debe reducir un problema utilizando un perfilador como OProfile o perf .

Es decir, ejecutar el perf record -a -g y luego leer los datos de perfil guardados en los perf data perf report mediante el perf report . Ver también: linux perf: cómo interpretar y encontrar puntos de acceso .


En su caso, el uso elevado de la CPU se debe a la competencia por /dev/urandom : solo permite leer un subproceso, pero varios procesos de Python lo están haciendo.

El módulo random Python lo está utilizando solo para la inicialización. Es decir:

 $ strace python -c 'import random; while True: random.random()' open("/dev/urandom", O_RDONLY) = 4 read(4, "\16\36\366\36}"..., 2500) = 2500 close(4) <--- /dev/urandom is closed 

También puede solicitar explícitamente /dev/urandom utilizando os.urandom o la clase SystemRandom . Así que revisa tu código que trata con números aleatorios.