Aggiornamento:le versioni più recenti di taskset hanno un -a
/--all-tasks
opzione che "opera su tutte le attività (thread) per un dato pid" e dovrebbe risolvere il comportamento che mostro di seguito.
Ho scritto uno script Python che avvia semplicemente alcuni thread e brucia i cicli della CPU. L'idea è di testare il taskset contro di esso, dato che è abbastanza semplice.
#!/usr/bin/env python
import threading
def cycle_burner():
while True:
meh = 84908230489 % 323422
for i in range(3):
thread = threading.Thread(target=cycle_burner)
print "Starting a thread"
thread.start()
La sola esecuzione dello script Python consuma circa il 150% dell'utilizzo della CPU.
[~/cbench]$ ./burn_cycles.py
Starting a thread
Starting a thread
Starting a thread
L'avvio del mio script Python con taskset funziona come previsto. Guardare in alto mostra il processo Python ancorato al 100% di utilizzo.
[~/cbench]$ taskset -c 0 ./burn_cycles.py
Starting a thread
Starting a thread
Starting a thread
È interessante notare che l'avvio dello script Python e quindi l'utilizzo immediato di taskset per impostare l'affinità del processo appena avviato limita il processo al 100%. Si noti dall'output che lo scheduler Linux ha terminato l'esecuzione dei comandi Bash prima di generare i thread Python. Quindi, il processo Python è stato avviato, quindi è stato impostato per essere eseguito sulla CPU 0, quindi ha generato i suoi thread, che hanno ereditato l'affinità corretta.
[~/cbench]$ ./burn_cycles.py &; taskset -pc 0 `pgrep python`
[1] 8561
pid 8561's current affinity list: 0-3
pid 8561's new affinity list: 0
Starting a thread
[~/cbench]$ Starting a thread
Starting a thread
Tale risultato contrasta con questo metodo, che è esattamente lo stesso ma consente la generazione dei thread Python prima di impostare l'affinità del processo Python. Questo replica i risultati "taskset non fa nulla" che ho descritto sopra.
[~/cbench]$ ./burn_cycles.py &
[1] 8996
[~/cbench]$ Starting a thread
Starting a thread
Starting a thread
[~/cbench]$ taskset -pc 0 `pgrep python`
pid 8996's current affinity list: 0-3
pid 8996's new affinity list: 0
Cosa c'è che non va qui?
Apparentemente i thread generati prima che l'affinità del processo genitore venga modificata non ereditano l'affinità del loro genitore. Se qualcuno potesse modificare un link alla documentazione che spiega questo, sarebbe utile.
Penso che dovrai chiamare taskset una volta per thread, ovvero utilizzare ps -eL
invece di pgrep
e reindirizzalo a taskset -cp 0
ps -eLo cmd,tid | grep python | perl -pe 's/.* (\d+)$/\1/' | xargs -n 1 taskset -cp 0
Questo chiama task set per tutti gli ID thread.
prova numactl con --physcpubind
(o -C
) invece. La pagina man dice:
... La politica è impostata per comando ed ereditata da tutti i suoi figli.
(nelle versioni recenti di taskset
c'è anche un -a
opzione quale Sets or retrieves the CPU affinity of all the tasks (threads) for a given PID.
ma non è chiaro se questo funzioni anche per i processi figli di un'attività avviata con taskset
anziché modificare un processo già in esecuzione)