2013-05-09 10 views
6

A volte, quando ho eseguito questo semplice programmaLo scheduler dei thread di Windows è ingiusto?

#include <Windows.h> 

DWORD WINAPI ThreadStart(LPVOID) 
{ 
    for (;;) { } 
    return 0; 
} 

int _tmain() 
{ 
    SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); 

    SYSTEM_INFO si; 
    GetSystemInfo(&si); 
    for (DWORD i = si.dwNumberOfProcessors * 2; i > 0; i--) 
    { CloseHandle(CreateThread(NULL, 0, &ThreadStart, NULL, 0, NULL)); } 

    Sleep(INFINITE); 
} 

osservo costantemente ingiusto programmazione dei thread, come ad esempio:

Screenshot

Non è eccessivo per ogni corsa, ma quando si è, rimane ingiusto per tutta la durata dell'applicazione.

Perché ciò accade e quale è il modo corretto per evitarlo?

+0

Che tipo di CPU hai? In realtà è un quad-core o dual-core con hyperthreading? – selbie

+0

Inoltre, quale versione di Windows. Anche questo è importante sapere. – selbie

+0

@selbie: 2-core HT (Core i5, è un laptop), Windows 8 x64. – Mehrdad

risposta

1

Alcune opzioni:


Se (e solo se) si sta eseguendo Windows 7/8 a 64 bit (non a 32 bit) o ​​Windows Server 2008 R2 o versione successiva, è possibile bypassare completamente il programma di pianificazione del sistema e prendersi cura di sé, anche se non è un'impresa banale!

È described on MSDN here e si chiama Pianificazione modalità utente (UMS).

Schermata parziale da MSDN in basso - è questo qualsiasi uso per voi?

enter image description here

Inoltre, potrebbe essere un'idea per disabilitare l'hyper-threading nel BIOS (se del caso) perché c'è un certo dibattito su come di Windows distingue tra i core logici e fisici. See here for a discussion.

Ci sono anche alcune funzioni disponibili come SetThreadAffinityMask() (MSDN here) e SetThreadIdealProcessor() che possono aiutare anche se personalmente ho trovato che questo è un po 'approssimativo. È più spesso il caso che io danneggi il rendimento generale piuttosto che aiutarlo.

+0

Non riesco a disabilitare HT in quanto l'opzione non è presente (né voglio ... né capisco perché cambi qualcosa). Sfortunatamente impostare l'affinità o il processore ideale non cambia nulla. UMS sembra essere massicciamente eccessivo e non sono sicuro che sarebbe di aiuto se non +1 per menzionarlo, sembra che potrebbe funzionare. – Mehrdad

0

Questo è uno sparo nell'oscura ipotesi.

Ma ho intenzione di suggerire che Hyper-Threading può essere di distorsione dei risultati un po '.

Se il bios/cmos del tuo laptop consente di disabilitare l'hyperthreading come fanno alcuni computer, sarebbe interessante vedere i numeri con il tuo codice solo in esecuzione su core reali.

E anche se HT è il motivo per cui distorce il filo, allora io ancora non so il motivo per cui l'avrebbe fatto.

+0

No, non posso disabilitare HT e, come hai detto, non spiega affatto quello che sto ottenendo. – Mehrdad

1

Lo vedrete su un sistema multiprocessore ogni volta che viene eseguito un thread che non fa parte del programma. Supponiamo che ci sia un task di sistema che si avvia per funzionare per un paio di secondi, eseguendo la scansione di assembly .NET o qualcosa del genere. Batterebbe uno dei tuoi thread fuori dalla pianificazione per un certo numero di intervalli temporali mentre i thread sugli altri core continuano a funzionare. Il thread che è stato eliminato non raggiungerà mai gli altri.

+1

Questo continua per sempre. Non sto contando i cicli assoluti, sto contando l'utilizzo della CPU, che non ha nulla a che fare con la storia passata del thread. Inoltre, non c'è nessun task di sistema, ecc., Che sta causando questo - questo è l'unico programma in esecuzione, ovviamente molto facile da dire dal task manager o da strumenti del genere. – Mehrdad

0

Sul mio sistema, SetThreadAffinityMask sembra attenuare il problema. C'è ancora uno squilibrio, apparentemente a causa di un nucleo che ha meno tempo a disposizione rispetto all'altro, ma non è così grave.

Windows sembra non voler spostare questi fili tra i core; raramente cambiano core dopo il primo secondo circa.Se i thread non sono equamente distribuiti tra i core, i tempi di thread lo riflettono.

Questo è il codice che ho usato per provare le maschere di affinità:

#include <Windows.h> 
#include <stdio.h> 

DWORD WINAPI ThreadStart(LPVOID arg) 
{ 
    DWORD pn1, pn2; 

    printf("Thread %u on processor %u\n", GetThreadId(GetCurrentThread()), pn1 = GetCurrentProcessorNumber()); 

    // The problem comes back if you enable this line 
    // SetThreadAffinityMask(GetCurrentThread(), -1); 

    for (;;) 
    { 
     for (int i = 0; i < 10000; i++); 
     pn2 = GetCurrentProcessorNumber(); 
     if (pn2 != pn1) 
     { 
      pn1 = pn2; 
      printf("Thread %u on processor %u\n", GetThreadId(GetCurrentThread()), pn1); 
     } 
    } 
    return 0; 
} 

int main(int argc, char ** argv) 
{ 
    SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); 

    SYSTEM_INFO si; 
    GetSystemInfo(&si); 

    for (DWORD i = 0; i < si.dwNumberOfProcessors; i++) 
    { 
     SetThreadAffinityMask(CreateThread(NULL, 0, &ThreadStart, NULL, 0, NULL), 1 << i); 
     SetThreadAffinityMask(CreateThread(NULL, 0, &ThreadStart, NULL, 0, NULL), 1 << i); 
    } 

    Sleep(INFINITE); 
    return 0; 
} 

Questo approccio sembra anche di mitigare il problema, anche se forse non nel modo più efficace:

#include <Windows.h> 
#include <stdio.h> 

DWORD WINAPI ThreadStart(LPVOID arg) 
{ 
    for (;;); 
    return 0; 
} 

int main(int argc, char ** argv) 
{ 
    SYSTEM_INFO si; 
    GetSystemInfo(&si); 

    for (DWORD i = si.dwNumberOfProcessors * 2; i > 0; i--) 
    { 
     CreateThread(NULL, 0, &ThreadStart, NULL, 0, NULL); 
    } 

    for (;;) 
    { 
     SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); 
     Sleep(100); 
     SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); 
    } 

    return 0; 
} 

Ho il sospetto che noi' stiamo guardando ad una qualche misura di risparmio energetico progettata partendo dal presupposto che i thread a bassa priorità non abbiano bisogno di una programmazione equa. (Probabilmente, impostare un thread o un processo su bassa priorità dice "Non mi interessa quanta CPU ottengo.")

Problemi correlati