Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Con le tecnologie di risparmio energia che diventano più comuni nei computer di oggi, un metodo comunemente usato per ottenere tempi cpu ad alta risoluzione, l'istruzione RDTSC, potrebbe non funzionare più come previsto. Questo articolo suggerisce una soluzione più accurata e affidabile per ottenere intervalli di CPU ad alta risoluzione usando le API di Windows QueryPerformanceCounter e QueryPerformanceFrequency.
- in background
- raccomandazioni
- di compatibilità delle applicazioni
Sfondo
Dall'introduzione del set di istruzioni x86 P5, molti sviluppatori di giochi hanno usato il contatore timestamp di lettura, l'istruzione RDTSC, per eseguire tempi ad alta risoluzione. I timer multimediali windows sono abbastanza precisi per l'elaborazione audio e video, ma con tempi di fotogrammi di una dozzina di millisecondi o meno, non hanno una risoluzione sufficiente per fornire informazioni in tempo differenziale. Molti giochi usano ancora un timer multimediale all'avvio per stabilire la frequenza della CPU e usano tale valore di frequenza per ridimensionare i risultati da RDTSC per ottenere un tempo accurato. A causa delle limitazioni di RDTSC, l'API Windows espone il modo più corretto per accedere a questa funzionalità tramite le routine di QueryPerformanceCounter e QueryPerformanceFrequency.
Questo uso di RDTSC per la tempistica soffre di questi problemi fondamentali:
- Valori discontinui. L'uso diretto di RDTSC presuppone che il thread sia sempre in esecuzione sullo stesso processore. I sistemi multiprocessore e dual core non garantiscono la sincronizzazione dei contatori dei cicli tra core. Ciò è esacerbato quando combinato con le moderne tecnologie di risparmio energia che inattive e ripristinano vari core in momenti diversi, il che comporta in genere la disattivazione della sincronizzazione dei core. Per un'applicazione, questo in genere comporta errori o potenziali arresti anomali quando il thread passa tra i processori e ottiene valori di intervallo che generano delta di grandi dimensioni, delta negativi o tempi interrotti.
- Disponibilità di hardware dedicato. RDTSC blocca le informazioni di temporizzazione richieste dall'applicazione al contatore del ciclo del processore. Per molti anni questo è stato il modo migliore per ottenere informazioni di temporizzazione ad alta precisione, ma le schede madri più recenti sono ora inclusi dispositivi di temporizzazione dedicati che forniscono informazioni di temporizzazione ad alta risoluzione senza gli svantaggi di RDTSC.
- Variabilità della frequenza della CPU. Il presupposto è spesso fatto che la frequenza della CPU è fissa per la vita del programma. Tuttavia, con le moderne tecnologie di risparmio energia, si tratta di un presupposto errato. Sebbene inizialmente limitato ai computer portatili e ad altri dispositivi mobili, la tecnologia che modifica la frequenza della CPU è in uso in molti PC desktop di fascia alta; la disabilitazione della funzione per mantenere una frequenza coerente non è in genere accettabile per gli utenti.
Consigli
I giochi necessitano di informazioni accurate sulla tempistica, ma devi anche implementare il codice di temporizzazione in modo da evitare i problemi associati all'uso di RDTSC. Quando si implementano tempi ad alta risoluzione, seguire questa procedura:
Usare queryPerformanceCounter e QueryPerformanceFrequency anziché RDTSC. Queste API possono usare RDTSC, ma potrebbero invece usare dispositivi di temporizzazione nella scheda madre o altri servizi di sistema che forniscono informazioni di temporizzazione ad alta risoluzione di alta qualità. Anche se RDTSC è molto più veloce di QueryPerformanceCounter, poiché quest'ultimo è una chiamata API, è un'API che può essere chiamata diverse centinaia di volte per fotogramma senza alcun impatto evidente. Tuttavia, gli sviluppatori devono tentare di chiamare i propri giochi QueryPerformanceCounter il minor possibile per evitare eventuali penalità delle prestazioni.
Quando si calcolano i delta, i valori devono essere bloccati per garantire che eventuali bug nei valori di intervallo non causi arresti anomali o calcoli temporali instabili. L'intervallo di blocco deve essere compreso tra 0 (per evitare valori differenziali negativi) e un valore ragionevole in base alla frequenza dei fotogrammi prevista più bassa. È probabile che il blocco sia utile in qualsiasi debug dell'applicazione, ma assicurarsi di tenere presente se si esegue l'analisi delle prestazioni o si esegue il gioco in modalità non ottimizzata.
Calcolare tutti i tempi in un singolo thread. Il calcolo della tempistica su più thread, ad esempio con ogni thread associato a un processore specifico, riduce notevolmente le prestazioni dei sistemi multi-core.
Impostare tale thread singolo per rimanere in un singolo processore usando l'API Di Windows SetThreadAffinityMask. In genere, questo è il thread principale del gioco. Anche se QueryPerformanceCounter e QueryPerformanceFrequency in genere modificare per più processori, i bug nel BIOS o i driver possono comportare la restituzione di valori diversi quando il thread passa da un processore a un altro. Quindi, è consigliabile mantenere il thread su un singolo processore.
Tutti gli altri thread devono funzionare senza raccogliere i propri dati timer. Non è consigliabile usare un thread di lavoro per calcolare i tempi, perché questo diventerà un collo di bottiglia della sincronizzazione. I thread di lavoro devono invece leggere i timestamp dal thread principale e, poiché i thread di lavoro usano solo timestamp di lettura, non è necessario usare sezioni critiche.
Chiamare QueryPerformanceFrequency una sola volta, perché la frequenza non cambia mentre il sistema è in esecuzione.
Compatibilità delle applicazioni
Molti sviluppatori hanno fatto ipotesi sul comportamento di RDTSC in molti anni, quindi è abbastanza probabile che alcune applicazioni esistenti presentino problemi quando vengono eseguiti in un sistema con più processori o core a causa della tempistica di implementazione. Questi problemi si manifestano in genere come movimenti di glitch o lentezza. Non esiste un rimedio semplice per le applicazioni che non sono a conoscenza del risparmio energia, ma esiste uno shim esistente per forzare l'esecuzione di un'applicazione su un singolo processore in un sistema multiprocessore.
Per creare questo shim, scaricare Microsoft Application Compatibility Toolkit da Windows Application Compatibility.
Usando l'amministratore della compatibilità, parte del toolkit, creare un database dell'applicazione e le correzioni associate. Creare una nuova modalità di compatibilità per questo database e selezionare la correzione di compatibilità SingleProcAffinity per forzare l'esecuzione di tutti i thread dell'applicazione in un singolo processore/core. Usando lo strumento da riga di comando Fixpack.exe (anche parte del toolkit), è possibile convertire questo database in un pacchetto installabile per l'installazione, il test e la distribuzione.
Per istruzioni sull'uso di Compatibility Administrator, vedere la documentazione del toolkit. Per la sintassi per ed esempi di utilizzo di Fixpack.exe, vedere la guida della riga di comando.
Per informazioni orientate ai clienti, vedere gli articoli della Knowledge Base seguenti della Guida e del supporto tecnico Microsoft:
- Programmi che usano la funzione QueryPerformanceCounter potrebbero non funzionare correttamente in Windows Server 2003 e in Windows XP (articolo 895980)