Sto eseguendo il porting di un codice in Windows e ho trovato che il threading è estremamente lento. L'attività richiede 300 secondi su Windows (con due xeon E5-2670 8 core 2.6ghz = 16 core) e 3,5 secondi su linux (xeon E5-1607 4 core 3ghz). Utilizzando vs2012 express.Porting di thread su Windows. Le sezioni critiche sono molto lente
Ho 32 thread che chiamano EnterCriticalSection(), eseguono un lavoro di 80 byte di un file std :: stack, LeaveCriticalSection e fanno un po 'di lavoro (250k di lavoro in totale).
Prima e dopo ogni chiamata di sezione critica, stampo l'ID del filetto e l'ora corrente.
- Il tempo di attesa per il blocco di un singolo filo è ~ 160ms
- a comparsa il lavoro dallo stack prende ~ 3 ms
- congedo Calling prende ~ 3 ms
- Il lavoro prende ~ 1 ms
(all'incirca lo stesso per Debug/Rilascio, Debug impiega un po 'di più. Mi piacerebbe essere in grado di profilare correttamente il codice: P)
Commentare la chiamata di lavoro rende l'intero processo di 2 secondi (ancora più di Linux).
Ho provato sia queryperformancecounter che timeGetTime, entrambi forniscono lo stesso risultato.
AFAIK il lavoro non effettua mai alcuna chiamata di sincronizzazione, ma non posso spiegare il rallentamento a meno che non lo faccia.
Non ho idea del motivo per cui copiare da una pila e chiamare pop richiede così tanto tempo. Un'altra cosa molto confusa è perché una chiamata a lasciare() richiede così tanto tempo.
Qualcuno può speculare sul perché funziona così lentamente?
Non avrei mai pensato che la differenza di processore avrebbe dato una differenza di prestazioni di 100 volte, ma potrebbe essere correlata a due CPU? (dovendo sincronizzare tra CPU separate rispetto ai core interni).
A proposito, sono a conoscenza di std :: thread ma voglio che il mio codice libreria funzioni con pre C++ 11.
modificare
//in a while(hasJobs) loop...
EVENT qwe1 = {"lock", timeGetTime(), id};
events.push_back(qwe1);
scene->jobMutex.lock();
EVENT qwe2 = {"getjob", timeGetTime(), id};
events.push_back(qwe2);
hasJobs = !scene->jobs.empty();
if (hasJobs)
{
job = scene->jobs.front();
scene->jobs.pop();
}
EVENT qwe3 = {"gotjob", timeGetTime(), id};
events.push_back(qwe3);
scene->jobMutex.unlock();
EVENT qwe4 = {"unlock", timeGetTime(), id};
events.push_back(qwe4);
if (hasJobs)
scene->performJob(job);
e la classe mutex, con roba linux #ifdef rimosso ...
CRITICAL_SECTION mutex;
...
Mutex::Mutex()
{
InitializeCriticalSection(&mutex);
}
Mutex::~Mutex()
{
DeleteCriticalSection(&mutex);
}
void Mutex::lock()
{
EnterCriticalSection(&mutex);
}
void Mutex::unlock()
{
LeaveCriticalSection(&mutex);
}
Cosa stavi usando su Linux? Stai proteggendo solo l'accesso allo std :: stack con le sezioni critiche? – xanatos
Dove stampate l'id del thread e l'ora corrente? – avakar
Scegli una lingua. E questo sembra strano. Sicuramente * sembra * abbastanza semplice da consentire a [SSCCE] (http://www.sscce.org) di funzionare. Concordo che la mia esperienza su Windows è stata alquanto scialba rispetto a una distro Linux adeguatamente equipaggiata, ma questa sembra davvero una voragine piuttosto ampia. – WhozCraig