CPU legat

Afinitatea procesorului , sau afinitatea procesorului , sau afinitatea cache , este o  tehnologie care asigură că un proces sau un fir de execuție este fixat și detașat de un anumit nucleu CPU, CPU sau set de procesoare, astfel încât procesul sau firul de execuție să ruleze numai pe nucleul specificat , procesor sau procesoare și nu pe niciun procesor dintr-un sistem multiprocesor. Afinitatea procesorului poate fi considerată ca o modificare a algoritmului central de programare a cozii de sarcini într-un sistem de operare multiprocesor. Fiecare articol din coada de sarcini are asociată o etichetă , care specifică procesoarele „înrudite”.

Când resursele sunt alocate, fiecare sarcină este de preferință distribuită pentru execuție pe unul dintre procesoarele „înrudite”. Afinitatea procesorului exploatează faptul că datele și setările unui proces care rula anterior pe un anumit procesor pot fi mai rapid disponibile pentru acel procesor decât pentru altul. Acest lucru se poate întâmpla, de exemplu, datorită stocării în cache a datelor de proces în memoria cache a procesorului, precum și în alte situații. Programarea unui astfel de proces pentru a rula pe același procesor îi îmbunătățește performanța prin reducerea evenimentelor care degradează performanța, cum ar fi pierderile de cache.

În plus, în unele sisteme, fiecare dintre procesoare poate avea acces mai rapid la o regiune de RAM care este aproape de aceasta. În același timp, se dovedește a fi rațional să păstrăm o legătură constantă a procesului cu procesorul, al cărui acces la RAM, unde se află datele acestui proces, este mai rapid.

Un exemplu practic de afinitate cu procesorul este rularea mai multor instanțe ale unei aplicații fără fire, cum ar fi unele software de randare grafică.

Implementarea algoritmului de programare a sarcinilor, care oferă posibilitatea legării la procesor, este implementată ținând cont de caracteristicile procesoarelor specifice și de construcția unui sistem multiprocesor, care va fi controlat de un astfel de algoritm. Unele implementări, în anumite circumstanțe, vor permite ca o sarcină să fie transferată la un alt procesor, depășind legarea. Acest lucru se face în acele cazuri când, din punctul de vedere al planificatorului, o astfel de comutare va duce la o creștere a eficienței executării sarcinilor. De exemplu, atunci când două sarcini care necesită mult procesor (A și B) sunt legate de același procesor și celălalt procesor nu este utilizat, mulți programatori vor comuta sarcina B la al doilea procesor pentru a profita la maximum de procesor disponibil pentru sistem. . Legarea sarcinii B la noul procesor la un astfel de moment va fi stabilită de planificatorul însuși.

Caracteristici de implementare

Afinitatea procesorului poate reduce în mod eficient problemele legate de intrarea datelor în sistem și/sau în memoria cache a procesorului. Dar nu oferă o soluție la problemele de echilibrare a sarcinii [1] . Afinitatea CPU este mai complexă în sistemele cu o arhitectură eterogenă, necesitând o logică de planificare mai sofisticată decât în ​​sistemele complet omogene. De exemplu, un sistem cu două CPU -uri dual-core , fiecare dintre ele acceptând tehnologia Hyper-Threading , prezintă o problemă pentru algoritmul de planificare, care presupune afinitatea CPU. Dacă sistemul are un număr și mai mare de procesoare și, de exemplu, nu este complet simetric în sine, atunci complexitatea problemei planificării eficiente a sarcinilor crește și mai mult.

Pentru exemplul de mai sus cu două procesoare dual-core hyper-threaded, planificatorul trebuie să implementeze un sistem de legare pe două niveluri. În ceea ce privește eficiența cache-ului, lucrul în același nucleu pe fire diferite este echivalent, iar planificatorul are dreptul de a muta liber o sarcină de la thread la thread. Nivelul de „proximitate” al diferitelor nuclee dintr-un procesor este mai scăzut, deoarece acestea împart parțial un cache al procesorului comun, nivelul de „proximitate” al diferitelor procesoare este și mai mic. Deoarece sunt partajate și alte resurse, afinitatea CPU singură nu poate fi folosită ca bază pentru programarea sarcinilor. De exemplu, dacă un proces a rulat recent pe un CPU virtual hiper-threading într-un nucleu și acel CPU virtual este ocupat în prezent, dar un al doilea CPU virtual din același nucleu este inactiv, afinitatea CPU bazată pe eficiența cache-ului implică faptul că procesul trebuie transferat la un al doilea procesor virtual (nu rulează) din același nucleu. Cu toate acestea, cele două procesoare virtuale concurează pentru aproape toate resursele de calcul, memoria cache și resursele de memorie. În această situație, de regulă, ar fi mai eficient să atribuiți procesul unui alt nucleu sau CPU, dacă printre ele există și inactiv. Acest lucru poate duce la o pierdere unică de performanță din cauza faptului că procesul relocat va trebui să umple din nou memoria cache cu datele sale. Dar performanța generală poate fi mai bună, deoarece cele două procese nu trebuie să concureze pentru resurse în cadrul aceluiași CPU.

Pentru a obține o eficiență maximă, planificatorul de sarcini trebuie să țină cont de toate aceste aspecte. Sistemele cu niveluri și mai mari de asimetrie ( NUMA , clustere etc.) necesită și mai multă complexitate din partea programatorului.

Implementare în sisteme de operare specifice

Pe Linux, afinitatea procesorului unui proces poate fi găsită sau setată folosind utilitarul taskset [2] . Din punct de vedere programatic, aceleași acțiuni pot fi efectuate folosind apelurile de sistem sched_getaffinity și sched_setaffinity [3] . Afinitatea firului de execuție poate fi setată sau modificată folosind una dintre funcțiile bibliotecii: pthread_setaffinity_np [4] sau pthread_attr_setaffinity_np [5] .

Pe sistemele SGI , un proces ar putea fi asociat cu un set de procesoare folosind utilitarul dplace [6] .

În DragonFly BSD 1.9 (2007) și mai târziu, apelul de sistem usched_set [7] [8] poate fi utilizat pentru a controla afinitatea CPU . În NetBSD 5.0, FreeBSD 7.2, DragonFly BSD 4.7 și mai târziu, apelurile de sistem pthread_setaffinity_np și pthread_getaffinity_np [9] pot fi utilizate . În NetBSD , utilitarul [10] psrset setează afinitatea unui fir de execuție la un anumit set de procesoare. FreeBSD folosește utilitarul cpuset [11] pentru a crea seturi de procesoare și a atribui procese acelor seturi. În DragonFly BSD 3.1 (2012) și mai târziu, utilitarul usched poate fi utilizat pentru a atribui procese unui set specific de procesoare [12] .

Pe Windows NT și versiuni ulterioare, afinitățile firelor și proceselor pot fi setate separat folosind apelurile API SetThreadAffinityMask [13] și SetProcessAffinityMask [14] sau prin interfața Task Manager (doar pentru procese).

macOS oferă un API de legare [15] care oferă indicii nucleului sistemului de operare despre cum să programați firele de execuție în funcție de seturile de legare.

Pe Solaris , puteți controla legarea proceselor și proceselor ușoare la procesor folosind utilitarul pbind [16] . Este de asemenea furnizat apelul de sistem procesor_bind [17] . Sunt disponibile și apeluri de interfață de nivel superior, și anume pset_bind [18] sau lgrp_affinity_get [19] , folosind conceptele de set de procesoare și respectiv grup de localități.

Pe AIX , puteți gestiona legările de proces utilizând utilitarul bindprocessor [20] [21] și apelul de sistem bindprocessor [20 ] [ 22 ] .

z/OS implementează poate cel mai sofisticat programator de sarcini utilizat astăzi. Oferă o redistribuire în schimbare dinamică a resurselor hardware între procese, inclusiv cele bazate pe legarea proceselor la nuclee individuale de procesor, procesoare și grupurile acestora [23]

Suport în limbaje de programare

Biblioteca standard pentru limbajul de programare paralel Julia include suport experimental pentru afinitatea proces-la-procesor [24] .

Note

  1. „White Paper - Processor Affinity” Arhivat 8 iunie 2021 la Wayback Machine  - la tmurgent.com Arhivat 28 aprilie 2020 la Wayback Machine .
  2. taskset(1) -  Pagina de manual pentru dezvoltatori Linux - comenzi personalizate  
  3. sched_setaffinity(2) -  Pagina de manual pentru dezvoltatori Linux - apeluri   de sistem
  4. pthread_setaffinity_np(3) -  Pagina de manual pentru dezvoltatori Linux - funcții de bibliotecă  
  5. pthread_attr_setaffinity_np(3) -  Pagina de manual pentru dezvoltatori Linux - funcții de bibliotecă  
  6. dplace.1 Arhivat 1 iulie 2007.  — De la sgi.com Arhivat 27 martie 2009 la Wayback Machine . Accesat 2007-07-06.
  7. usched_set(2)- setarea unui proces usched . Manual de apeluri de sistem DragonFly . DragonFlyBSD . Preluat: 28 iulie 2019.
  8. . Referință încrucișată BSD . DragonFlyBSD . Preluat: 28 iulie 2019.kern/kern_usched.c § sys_usched_set
  9. pthread_setaffinity_np(3)  - Manualul funcțiilor bibliotecii NetBSD , FreeBSD și DragonFly BSD
  10. psrset(8) -  Pagina de manual pentru administratorul de sistem NetBSD  
  11. cpuset(1)  - Pagina de manual pentru comenzile utilizatorului FreeBSD  
  12. usched(8)- rulați un program cu un program de planificare userland și cpumask specificate . Manualul managerului de sistem DragonFly . DragonFlyBSD . Preluat: 28 iulie 2019.
  13. SetThreadAffinityMask Arhivat 24 aprilie 2008 la Wayback Machine  - MSDN Library
  14. SetProcessAffinityMask Arhivat 25 martie 2008 la Wayback Machine  - MSDN Library
  15. Note de lansare Thread Affinity API . developers.apple.com _ Preluat la 27 mai 2020. Arhivat din original la 9 aprilie 2012.
  16. pbind(1M) Arhivat 25 februarie 2021 pe pagina de manual Wayback Machine  - Solaris
  17. processor_bind(2) Arhivat la 3 septembrie 2016 pe pagina de manual Wayback Machine  - Solaris
  18. pset_bind(2) Arhivat 20 ianuarie 2022 la Wayback Machine  - Biblioteca de informații Oracle Solaris 11.1 - paginile de manual secțiunea 2
  19. lgrp_affinity_get(3LGRP) Arhivat 10 iunie 2016 la Wayback Machine  - Ghid pentru dezvoltatori de optimizare a plasării memoriei și a firelor
  20. 1 2 Umesh Prabhakar Gaikwad; Kailas S. Zadbuke. Afinitatea procesorului pe AIX (16 noiembrie 2006). Preluat la 27 mai 2020. Arhivat din original la 2 martie 2020.
  21. Comanda bindprocessor . IBM . Preluat la 27 mai 2020. Arhivat din original la 2 martie 2020.
  22. subrutină bindprocessor . IBM . Preluat la 27 mai 2020. Arhivat din original la 2 martie 2020.
  23. Ghid tehnic IBM zEnterprise 196. Bill White, Erik Bakker, Parwez Hamid, Octavian Lascu, Fernando Nogal, Frank Packeiser, Vicente Ranieri Jr., Karl-Erik Stenfors, Esra Ufacik, Chen Zhu, IBM Redbooks. octombrie 2011
  24. Discuție despre dezvoltatori