Linux 2.6.0: CPU affinitás

Címkék

Folytassuk a megjelenés előtt álló 2.6-os Linux kernellel való mélyebb ismerkedést. Az Linux kernel egyik régóta hiányzó funkciója az a képesség, hogy meg tudjuk határozni az SMP (több processzoros) rendszereken, hogy az egyes processzek melyik processzoron fussanak. A 2.5-ös fejlesztői kernelben - Robert M. Love-nak, a preempt kernelpatch szerzőjének köszönhetően - megjelentek a processzek bizonyos CPU-hoz való rendelését segítő rendszerhívások.

A CPU-hoz rendelésnek (affinitásnak) két fajtája van. Az egyik az ún. "soft", a másik pedig a "hard" CPU affinitás. A "soft" affinitás az ütemező azon tulajdonsága, amely azt biztosítja, hogy az egyes processzek lehetőleg mindig ugyanazon CPU-n fussanak. A 2.4-es kernel ütemezője sajnos nem nagyon volt felkészítve erre, benne a CPU "soft" affinitás gyenge volt. Ha az ütemező természetes affinitása nem elég kifinomult, akkor a processzek ide-oda ugrálhatnak a rendszer processzorain, amely egy nemkívánatos működése az operációs rendszernek. Nem nehéz belátni, hogy az állandóan ide-oda "költöző" processzek rosszabb hatásfokkal futnak, mintha többnyire egy CPU-n futnának.

A természetes, vagy "soft" CPU-hoz rendelés ellentétje az ún. "hard" CPU affinitás, amikoris valamilyen rendszerhívás segítségével rögzítünk egy folyamatot egy megadott processzorhoz. A leendő 2.6-os kernelben levő O(1) ütemező - köszönhetően Molnár Ingo-nak - nagyon jó természetes CPU affinitással rendelkezik. Ez azt jelenti, hogy az O(1) ütemező lehetőség szerint igyekszik arra, hogy egy folyamat lehetőleg ugyanazon processzoron fusson. De mi van olyankor, ha én azt szeretném, hogy egy több processzoros gép egyik processzora mondjuk dedikáltan egy feladattal törődjön? Ekkor jön képbe a "hard" CPU affinitás, azaz, egy rendszerhívás segítségével képes vagyok meghatározni, hogy egy bizonyos PID-del (process ID) rendelkező folyamat melyik CPU-n fusson.

Robert M. Love alkotta meg ezeket a rendszerhívásokat, amelyek a 2.5.8-pre3-as fejlesztői kerneltől érhetőek el. A használatukhoz legalább 2.3.1-es glibc szükséges.

Hogy hogyan tudjuk használni? Először is szükségünk van egy több processzoros rendszerre (vagy legalább egy Intel HyperThreading technológiával rendelkező gépre). A szükséges stuffokat letölthetjük a következő helyről:

http://www.kernel.org/pub/linux/kernel/people/rml/cpu-affinity/

A szükséges kernelpatchek is megtalálhatóak a fenti címen, de ha 2.6.0-testX kernelt futtatunk, akkor ezek már szükségtelenek. Ha SMP kernelt futtatunk, akkor nincs más teendőnk, mint letölteni a affinity-run.c forrást, és lefordítani a "bind" névre hallgató programocskát:

wget http://www.kernel.org/pub/linux/kernel/people/rml/cpu-affinity/affinity-run.c

gcc affinity-run.c -o bind

Ez egy egyszerű parancssori programocska, amelynek a működése az alábbi:

./bind pid cpu_mask

Azaz meg kell adni, hogy mi a futó processz PID-je, és hogy melyik processzoron szeretnénk azt kizárólag futtatni.

Ha például az MySQL adatbázis szerverünk a 304-es PID-del fut, és azt szeretném, hogy a későbbiekben csak a 2-es CPU-n fusson, akkor a következőket kell tenni:

sunshine:/home/trey# ./bind 304 2

pid 304's old affinity: 00000003

pid 304's new affinity: 00000002

Arra figyeljünk, hogy az affinitás állításához "root"-nak kell lennünk!

Ha azt szeretnénk, hogy a többi processz ne használja a 2-es CPU erőforrásait, akkor azokat költöztessük át az 1-es CPU-ra. Erre a legegyszerűbb megoldás az, ha kihasználjuk, hogy a CPU affinitás a fork() hívása után öröklődik. Azaz, ha az init-et az 1-es CPU-hoz rendeljük, akkor az összes gyerek (child) processz az 1-es CPU-n fog futni.

Ezek az új rendszerhívások hasznosak leszek azoknak, akik ún. virtuális processzorokat is használnak gépükben. Mint arról korábban írtam a Hyperthreading-képes processzorokhoz (is) nagyon hasznos lesz ez az új feature.

Referencia:

Robert M. Love: Kernel Korner: CPU Affinity