2013-07-06 43 views
7

Stavo giocando con la funzione time.sleep dalla libreria standard di python e l'ho trovata inadeguata per i ritardi sub-ms. Dal test ho trovato in realtà attendere 1.1-1.2 ms per un attesa di 1 ms. L'implementazione di un'attesa impegnata ha ottenuto una precisione dell'ordine dell'1%. Ho usato:Python time.sleep vs busy wait accuracy

def busy_wait(dt): 
    current_time = time.time() 
    while (time.time() < current_time+dt): 
     pass 

e potrebbe arrivare a 0,0001 secondi prima di rompere l'1% di precisione.

Le domande principali che ho sono:

  • Perché la funzione di sonno in modo inesatto (forse un problema di C)? Cambiare la CPU con una velocità di clock più alta?
  • Perché qualcuno dovrebbe usare il sonno? L'unico vantaggio che vedo, risparmio energetico, è limitato ai sistemi embedded, no?
  • Sarebbe utile compensare l'inaccuratezza del sonno con la calibrazione? In questo modo:
 
def sleep(dt): 
    sleep(calibration_function(dt)) 

Per inciso, ho letto che il sonno non ha nemmeno funziona bene con i lunghi tempi di attesa: Upper limit in Python time.sleep()? Ho anche letto da qualche parte su SO di fare un ciclo di intervalli di tempo più brevi per aumentare la precisione , ma è inutile quando voglio ritardare 0,01 sec. Karl Voigtland menziona l'uso del nanosleep del tipo, ma ritengo che questo sia eccessivo e che time.sleep dovrebbe fare il suo comportamento previsto.

time.sleep è una funzionalità di python non funzionante? O a nessuno interessa abbastanza la misurazione del tempo?

+1

possibile duplicato di [Quanto è accurato python's time.sleep()?] (Http://stackoverflow.com/questions/1133857/how-accurate-is-pythons-time-sleep) – g19fanatic

+0

Sì, ho pensato che fosse un Chiamata al sistema operativo, ma ora mi chiedo perché usano una chiamata del sistema operativo quando un'attesa è meglio. – JDong

+0

un'attesa impegnata fa schifo il tempo della CPU e blocca una CPU. Un sonno esegue un cambio di contesto e non blocca altre esecuzioni (blocca l'esecuzione). In generale, sei solo occupato ad aspettare se hai davvero bisogno del tempo esatto, e anche allora sei ancora limitato al bisogno del SO per CPU che potrebbe contestualizzarti comunque ... – g19fanatic

risposta

4

Su Windows, la funzione Sleep del sistema operativo (che Python utilizza necessariamente) può solo attivare un thread su un multiplo dell'intervallo del timer corrente. In genere questo intervallo tra 1,0 ms e 15,6 ms.Abbassando l'intervallo del timer può essere utile perché permette di posti letto più brevi, ma spreca l'elettricità, come ho scritto in questo articolo:

http://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/

occupato attesa può dare una migliore precisione, ma è generalmente un'idea orribile dal momento che rifiuti ancora di più l'elettricità e ruba il tempo di CPU da compiti più meritevoli:

https://randomascii.wordpress.com/2012/06/05/in-praise-of-idleness/

Infine, la precisione di occupato attesa dipenderà da quale funzione timer che si sta utilizzando per ottenere l'ora corrente, e può anche dipendere dal intervallo del timer:

https://randomascii.wordpress.com/2013/05/09/timegettime-versus-gettickcount/

Perché vuoi dormire per tali brevi periodi di tempo? Di solito sarebbe meglio aspettare che succedesse qualcosa - in attesa di un evento - piuttosto che aspettare tempi così brevi.

+0

In effetti Python 'time.sleep()' usa una chiamata 'WaitForSingleObject()' con un timeout per catturare qualsiasi Ctrl-C durante l'attesa (tramite 'SetConsoleCtrlHandler()' che segnala un evento.) – schlenk

+0

L'applicazione è una sorta di macro; Ho una serie di azioni che voglio simulare in modo accurato. Ho imparato come farlo in C, ma non ho ancora trovato la soluzione canonica in Python. La mia domanda è un po 'irrisolvibile, quindi accetterò la tua risposta per ora. Grazie per l'intuizione. – JDong

+0

@schlenk Grazie per le informazioni sull'implementazione di time.sleep(). Le regole su quando il timeout può scadere sono fondamentalmente le stesse di Sleep() (poiché lo scheduler viene eseguito solo quando succede qualcosa o quando scatta un interrupt del timer), quindi la risposta si applica ancora. –

0

Questa è una specie di domanda duplicata, ma proverò a rispondere qui in ogni caso al meglio delle mie possibilità.

La funzione di sospensione è una chiamata del sistema operativo che differisce dall'attesa di occupato in quanto non blocca il thread. Se si dispone di uno script multi-thread, tuttavia, non dovrebbe bloccare gli altri thread. La funzione sleep è imprecisa in Windows perché non è un sistema operativo in tempo reale (non è sicuro che cosa significhi). Se stai cercando rigorosamente la precisione dell'attesa, l'attesa è la strada da percorrere. Altrimenti, è probabilmente preferibile lo time.sleep(). Il motivo per cui il sistema operativo chiama a dormire è inaccurato è probabilmente perché si basa sul sistema operativo per tornare al momento giusto, e dipende dalla precisione dello scheduler del sistema operativo.