Threads Affinity!

Iniciado por Khronos14, 29 Agosto 2011, 02:32 AM

0 Miembros y 1 Visitante están viendo este tema.

Khronos14

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 (cpp) [Seleccionar]

#include <iostream>
#include <Windows.h>

using namespace std;

void threadFunc()
{
double a = 0;

for (unsigned long long i = 0;;i++)
{
a = (i * 17) - 32;
if (a > 0)
a = (sqrt(a) * 43) - 72;
}
}

int main(int argc, char * argv[])
{
SYSTEM_INFO sysInfo;
DWORD dwThreadId;

GetSystemInfo(&sysInfo);
cout << "Numero de nucleos: " << sysInfo.dwNumberOfProcessors << endl << endl;

BYTE coreToUse = 0; //Empieza en el 0
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadFunc, NULL, 0, &dwThreadId);

if (SetThreadAffinityMask(hThread, 1 << (coreToUse % 8)) != 0)
cout << "ThreadAffinity se establecio con exito en el nucleo " << (int)coreToUse << endl;
else
cout << "ThreadAffinity error! El sistema repartira la carga del Thread!" << endl;

cin.get();

return 0;
}


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.



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.



¿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().



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.

pucheto

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.