Aktualizace:Novější verze sady úloh mají -a
/--all-tasks
možnost, která "funguje na všech úlohách (vláknech) pro daný pid" a měla by vyřešit chování, které ukazuji níže.
Napsal jsem skript v Pythonu, který jednoduše roztáčí některá vlákna a vypaluje cykly CPU. Cílem je otestovat sadu úloh proti ní, protože je to docela jednoduché.
#!/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()
Pouhé spuštění skriptu Python spotřebuje asi 150 % CPU.
[~/cbench]$ ./burn_cycles.py
Starting a thread
Starting a thread
Starting a thread
Spuštění mého skriptu Python se sadou úloh funguje podle očekávání. Sledování nahoře ukazuje proces Pythonu fixovaný na 100% využití.
[~/cbench]$ taskset -c 0 ./burn_cycles.py
Starting a thread
Starting a thread
Starting a thread
Zajímavé je, že spuštění skriptu Python a následné okamžité použití taskset k nastavení afinity právě spuštěného procesu omezuje proces na 100 %. Všimněte si z výstupu, že plánovač Linuxu dokončil provádění příkazů Bash před vytvořením vláken Pythonu. Proces Pythonu byl tedy spuštěn, pak byl nastaven tak, aby běžel na CPU 0, pak vytvořil svá vlákna, která zdědila správnou afinitu.
[~/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
Tento výsledek kontrastuje s touto metodou, která je úplně stejná, ale umožňuje vláknům Pythonu, aby se vytvořila před nastavením afinity procesu Python. Toto replikuje výsledky „sada úkolů nedělá nic“, které jsem popsal výše.
[~/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
Co se tu děje?
Vlákna vytvořená před změnou afinity nadřazeného procesu zřejmě nedědí afinitu svého nadřazeného procesu. Pokud by někdo mohl upravit odkaz na dokumentaci, která to vysvětluje, bylo by to užitečné.
Myslím, že budete muset zavolat taskset jednou za vlákno, tj. použít ps -eL
místo pgrep
a nasměrujte to na taskset -cp 0
ps -eLo cmd,tid | grep python | perl -pe 's/.* (\d+)$/\1/' | xargs -n 1 taskset -cp 0
To volá task set pro všechna ID vláken.
zkuste numactl s --physcpubind
(nebo -C
) namísto. Manuová stránka říká:
... Zásada je nastavena pro příkaz a zděděna všemi jeho potomky.
(v posledních verzích taskset
existuje také -a
možnost, která Sets or retrieves the CPU affinity of all the tasks (threads) for a given PID.
ale není jasné, zda to funguje také pro dceřiné procesy úlohy spuštěné s taskset
na rozdíl od úpravy již běžícího procesu)