Windows-Scheduler

04/03/2008 - 18:34 von Elcaro Nosille | Report spam
Man liest ja immer wieder, dass der Windows-Scheduler Threads
so hàufig von einer auf die andere CPU verlege und dass das
nicht für die Güte des Schedulers spreche.
Jetzt wollte ich mal nachvollziehen wie oft dieses Verlagern
denn auf meiner Quadcore-CPU (Intel, 3GHz) passiert und schnell
ein kleines Progràmmchen geschrieben das eine wachsende Anzahl
an durchgehend arbeitenden Threads ihre eigenen Verlagerungen
anhand der APIC-IDs der Kerne (jeder Kern hat eine eigene ID
für den Interrupt-Controller die sich mit CPUID auslesen làsst);
es misst auch ob die Verlagerung eine teurere zwischen den Dies
der Quadcore-CPU oder eine günstige auf dem selben Die ist.

So, nun das Ergebnis:

| 1 parallel threads
| 6.10 core-switches per second
| 2.20 on-die core-switches per second
| 3.90 off-die core-switches per second
| 2 parallel threads
| 11.55 core-switches per second
| 5.25 on-die core-switches per second
| 6.30 off-die core-switches per second
| 3 parallel threads
| 15.77 core-switches per second
| 3.17 on-die core-switches per second
| 12.60 off-die core-switches per second
| 4 parallel threads
| 9.38 core-switches per second
| 4.40 on-die core-switches per second
| 4.97 off-die core-switches per second

Das Programm gibt hier an wie oft ein einzelner Thread im
Schnitt pro Sekunde verlagert wurde (Messzeitraum sind je-
weils 10 Sekunden). Auf der CPU lief sonst nix was Last
macht.
Ich finde die Hàufigkeit der Verlagerungen nicht wirklich
dramatisch.
Es kann ja mal jemand das selbe Ding für x86-Linux-Systeme
umschreiben.



#include "windows.h"
#include <stdio.h>

DWORD WINAPI HopperThread( LPVOID lpvThreadParam );

int main()
{
unsigned threads;
LONG alHopCounter[3];
HANDLE ahThreads[4];
DWORD const INTERVAL = 10;
DWORD dwThreadId;

for( threads = 1; threads <= 4; threads++ )
{
alHopCounter[0] = 0;
alHopCounter[1] = 0;
alHopCounter[2] = 0;

printf( "%d parallel threads", (int)threads );

for( unsigned thread = 0; thread < threads; thread++ )
ahThreads[thread] = CreateThread( NULL, 0, HopperThread, alHopCounter, CREATE_SUSPENDED, &dwThreadId );

for( unsigned thread = 0; thread < threads; thread++ )
ResumeThread( ahThreads[thread] );

Sleep( INTERVAL * 1000 );

for( unsigned thread = 0; thread < threads; thread++ )
TerminateThread( ahThreads[thread], 0 );

printf( " %.2lf core-switches per second", ((double)alHopCounter[0] / threads / INTERVAL) );
printf( " %.2lf on-die core-switches per second", ((double)alHopCounter[1] / threads / INTERVAL) );
printf( " %.2lf off-die core-switches per second", ((double)alHopCounter[2] / threads / INTERVAL) );
}

return 0;
}

BYTE __fastcall GetApicId();

DWORD WINAPI HopperThread( LPVOID lpvThreadParam )
{
BYTE bPreviousApicId,
bApicId;
LONG volatile *plHopCounter;

for( (plHopCounter = (LONG volatile *)lpvThreadParam,
bPreviousApicId = GetApicId()); ; )
{
if( (bApicId = GetApicId()) != bPreviousApicId )
{
InterlockedIncrement( &plHopCounter[0] );

if( (bApicId ^ bPreviousApicId) == 1 )
InterlockedIncrement( &plHopCounter[1] );
else
InterlockedIncrement( &plHopCounter[2] );

bPreviousApicId = bApicId;
}
}

return 0;
}

__declspec(naked)
BYTE __fastcall GetApicId()
{
__asm
{
push ebx
mov eax, 1
cpuid
mov eax, ebx
shr eax, 24
pop ebx
ret
}
}
 

Lesen sie die antworten

#1 Elcaro Nosille
04/03/2008 - 18:45 | Warnen spam
Achso; das Ergebnis kann natürlich je nach Last variieren.

Ähnliche fragen