Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Khronos14 en 29 Agosto 2011, 02:32 am



Título: Threads Affinity!
Publicado por: Khronos14 en 29 Agosto 2011, 02:32 am
El otro día estaba investigando la posibilidad de ejecutar un Thread en un núcleo específico del procesador y me encontré con esta función de la API de Windows: SetThreadAffinityMask().

Se define así:

DWORD_PTR WINAPI SetThreadAffinityMask(__in HANDLE hThread, __in DWORD_PTR dwThreadAffinityMask);

Usando el siguiente programa y el taskmanager de Windows hice las siguientes pruebas:

Código
  1. #include <iostream>
  2. #include <Windows.h>
  3.  
  4. using namespace std;
  5.  
  6. void threadFunc()
  7. {
  8. double a = 0;
  9.  
  10. for (unsigned long long i = 0;;i++)
  11. {
  12. a = (i * 17) - 32;
  13. if (a > 0)
  14. a = (sqrt(a) * 43) - 72;
  15. }
  16. }
  17.  
  18. int main(int argc, char * argv[])
  19. {
  20. SYSTEM_INFO sysInfo;
  21. DWORD dwThreadId;
  22.  
  23. GetSystemInfo(&sysInfo);
  24. cout << "Numero de nucleos: " << sysInfo.dwNumberOfProcessors << endl << endl;
  25.  
  26. BYTE coreToUse = 0; //Empieza en el 0
  27. HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadFunc, NULL, 0, &dwThreadId);
  28.  
  29. if (SetThreadAffinityMask(hThread, 1 << (coreToUse % 8)) != 0)
  30. cout << "ThreadAffinity se establecio con exito en el nucleo " << (int)coreToUse << endl;
  31. else
  32. cout << "ThreadAffinity error! El sistema repartira la carga del Thread!" << endl;
  33.  
  34. cin.get();
  35.  
  36. return 0;
  37. }
  38.  

En la variable coreToUse especificas que núcleo que vas a usar para ejecutar el thread con la función threadFunc(). En mi caso tengo como procesador un AMD Athlon X 2 6400 - 3.2 GHz, por lo tanto sólo tiene 2 núcleos.

(http://img641.imageshack.us/img641/6276/core0.png)

Como podéis ver en la imagen, el primer núcleo se pone al 100%.. Ahora voy a hacer lo mismo, pero poniendole el valor 1 a la variable coreToUse.

(http://img855.imageshack.us/img855/9964/core1.png)

¿Qué pasaría si le pongo un valor mayor que 1? Pues en mi caso, como solo tiene 2 núcleos mi procesador, fallaría la función SetThreadAffinityMask() y por lo tanto el sistema repartiría la carga de la función threadFunc().

(http://img204.imageshack.us/img204/6186/core2q.png)

No trabajan los dos núcleos lo mismo, siempre va a trabajar más uno que otro, pero eso depende de los algoritmos de planificación del scheduler del kernel de Windows...

Y ahora viene la gran pregunta, ¿Vale la pena utilizar esta API? La verdad, yo no le encontré gran utilidad. Quizás con 2 núcleos no te sirva de mucho, pero con 8 o 12 núcleos se podrían hacer bastantes cosas a la vez. Supongo que para los videojuegos o programas que necesiten gran capacidad de cálculo les será útil. Aunque siempre dependes de la cantidad de núcleos que tenga el equipo que ejecute tu programa.

Saludos.


Título: Re: Threads Affinity!
Publicado por: pucheto en 29 Agosto 2011, 05:02 am
Si, vale la pena, y muchisimo. Con 2 nucleos no hay mucha diferencia, pero cuando tenes muchos nucleos, y sobre todo si los tiempos de acceso a memoria ram no es uniforme ( una arquitectura NUMA ) es importante mantener la cache 'caliente'. Usando esto cada thread se ejecuta en el mismo procesador que se ejecuto la vez pasada intentando justamente tratar de mantener esta propiedad.