2015-05-14 3 views
9

Ho sviluppato un programma python che esegue pesanti calcoli numerici. Lo eseguo su una macchina Linux con 32 CPU Xeon, 64 GB di RAM e Ubuntu 14.04 a 64 bit. Lancio più istanze Python con parametri di modello diversi in parallelo per utilizzare più processi senza doversi preoccupare del blocco dell'interprete globale (GIL). Quando monito l'utilizzo della cpu usando htop, vedo che tutti i core sono usati, tuttavia il più delle volte dal kernel. Generalmente, l'ora del kernel è più del doppio del tempo dell'utente. Temo che ci sia un sacco di spese generali in corso a livello di sistema, ma non sono in grado di trovare la causa per questo.CPU ad alto kernel quando si eseguono più programmi python

Come si riduce l'utilizzo elevato della CPU del kernel?

Ecco alcune osservazioni che ho fatto:

  • Questo effetto sembra indipendente dal fatto che corro 10 posti di lavoro o 50. Se ci sono meno posti di lavoro rispetto core, non vengono utilizzati tutti i core, ma quelli che sono usato ancora avere un elevato utilizzo della CPU da parte del kernel
  • ho implementato il ciclo interno utilizzando numba, ma il problema non è legata a questo, dal momento che la rimozione della parte numba non risolve il problema
  • ho anche però che potrebbe essere relativo all'utilizzo di python2 simile al bu problem mentioned in this SO question Il passaggio da python2 a python3 non è cambiato molto
  • Ho misurato il numero totale di switch di contesto eseguiti dal sistema operativo, che è di circa 10000 al secondo. Non sono sicuro se questo è un gran numero
  • ho provato aumentando gli intervalli di tempo di pitone impostando sys.setcheckinterval(10000) (per python2) e sys.setswitchinterval(10) (per python3), ma niente di tutto questo ha aiutato
  • ho provato influenzare il task scheduler eseguendo schedtool -B PID ma questo non ha aiutato

Edit: Ecco uno screenshot di htop: enter image description here

ho anche eseguito perf record -a -g e questa è la relazione 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_irqresto▒ 
    0.06%   python3 python3.4         [.] PyEval_EvalFrameEx  

Sembra come se la maggior parte del tempo viene speso chiamando _raw_spin_lock_irqsave. Non ho idea di cosa significhi, però.

+0

Avete controllato cos'altro sta funzionando sul sistema? L'output di 'top' sarebbe interessante. – wallyk

+0

Non ho niente fuori dall'ordinario. Questo non è nemmeno il computer che utilizzo per il mio lavoro quotidiano. Ho aggiunto uno screenshot alla domanda. –

+0

Si prega di eseguire 'perf record -a' da root (chdir a'/tmp') e quindi 'perf report'. Ti darà un'idea di cosa sta facendo il kernel. – myaut

risposta

5

Se il problema persiste nel kernel, è necessario limitare un problema utilizzando un profiler come OProfile o perf.

I.e. eseguire perf record -a -g e poi leggere i dati di profilatura salvati in perf data utilizzando perf report. Vedi anche: linux perf: how to interpret and find hotspots.


Nella tua elevato utilizzo della CPU caso è causata da competizione per /dev/urandom - permette un solo thread per leggere da esso, ma più processi Python stanno facendo così.

Il modulo Python random lo utilizza solo per l'inizializzazione. IO.e:

$ 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 

Si può anche chiedere esplicitamente /dev/urandom utilizzando os.urandom o SystemRandom di classe. Quindi controlla il tuo codice che tratta di numeri casuali.

+2

Grazie mille per il vostro aiuto! Ora che sapevo cosa stavo cercando, mi sono reso conto che in effetti avevo un bug nella * mia * base di codice dove avrei dovuto in qualche modo inizializzare il generatore di numeri casuali ogni volta che veniva creato un certo oggetto base. Sono stato in grado di trovare quella parte solo in un vecchio codice perché sapevo esattamente cosa stavo cercando! Accetterò la tua risposta il prima possibile. –