Stavamo lavorando su nostro progetto lettore audio su Mac e ho notato che il consumo di energia era così alto (circa 7x quella di Google Chrome facendo lo stesso carico di lavoro.)perché una variabile condizionale fissa il nostro consumo di energia?
ho usato strumento di profiling di energia di Xcode, uno dei problemi era abbiamo avuto troppa CPU in testa.
Secondo Xcode:
Ogni volta che la CPU si sveglia dal minimo, c'è una penalità energetica sostenuti. Se le scie sono alte e l'utilizzo della CPU per scia è basso, è necessario considerare il lavoro di batching.
Abbiamo ridotto il problema a una chiamata di funzione usleep.
Nel nostro codice, il decodificatore audio è un produttore che produce dati audio e li inserisce nel consumatore - il lettore audio. Il nostro lettore audio è basato su OpenAL, che ha un buffer per i dati audio.
Poiché il lettore audio può essere più lento del produttore, controlliamo sempre la disponibilità del buffer prima di fornire nuovi dati audio al lettore audio. Se nessun buffer è disponibile, ci addormentiamo per un po 'e riproviamo. Così il codice è simile:
void playAudioBuffer(Data *data)
{
while(no buffer is available)
{
usleep()
}
process data.
}
Sapendo che usleep è un problema, la prima cosa che abbiamo fatto è stato semplicemente rimuovendo usleep(). (Poiché OpenAL non sembra fornire callback o in altro modo, il polling sembra essere l'unica opzione.) Abbiamo ridotto l'utilizzo di energia della metà dopo averlo fatto.
Poi, ieri, abbiamo provato
for(int i =0; i<attempts; ++i)
{
std::unique_lock<std::mutex> lk(m);
cv.wait_for(lk, 3, []{
available = checkBufferAvailable();
return available;
})
if (available)
{
process buf;
}
}
Questo è un esperimento che abbiamo provato per caso. Non ha senso per noi, poiché logicamente esegue la stessa attesa. E l'uso della variabile condizionale non è corretto, perché la variabile "disponibile" è accessibile solo da un thread. Ma in realtà ha ridotto il nostro consumo di energia del 90%, l'utilizzo della CPU del thread è diminuito molto. Ora siamo migliori di chrome. Ma come la variabile condizionale viene implementata in modo diverso dal seguente codice? Perché ci salva energia?
mutex lock;
while(condition is false)
{
mutex unlock;
usleep();
mutex lock;
}
...
mutex unlock
...
(Usiamo il monitor del Mac attività (numero di energia) e uno strumento di utilizzo di profilazione della CPU per misurare il consumo di energia.)
Forse il cv gira invece di dormire in alcuni casi? E forse fa uno spin lock "lento" o "low power" ... in qualche modo? (btw, 3 quali unità di tempo? Stiamo parlando di 'std :: condition_variable' qui? Come funziona 3?) Oh, non stai postando codice reale, stai trascrivendo manualmente e hai introdotto un numero sconosciuto di errori e omissioni. Per favore non farlo: per favore pubblica un codice che riproduca effettivamente la cosa che ti interessa. Ciò potrebbe comportare la semplificazione del codice esistente: se hai capito cosa ha causato la tua cosa interessante, non ti staresti chiedendo qui! – Yakk
Oppure potresti semplicemente aspettare più a lungo con una condizione in confronto a noi addormentati? – Lol4t0
in entrambi i casi aspettiamo 3 millisecondi e riproviamo. abbiamo provato ad esempio 4 millisecondi e notato singhiozzo –