Qual è un buon esempio di utilizzo delle variabili di registro in C?
-
10-07-2019 - |
Domanda
Sto leggendo K & amp; R e sono arrivato alla piccola sezione sulle variabili di registro, e mi chiedevo se le persone qui hanno alcuni buoni esempi di questo messo in pratica.
Dalla sezione 4.7 in K & amp; R:
La dichiarazione di registro appare come
registrati int x;
registra char c;
Per essere chiari, spero solo di vedere alcuni esempi di codici interessanti. Sono (sono abbastanza sicuro di aver capito) l'argomento, quindi non sento il bisogno di scrivere una spiegazione dettagliata (a meno che tu non voglia).
Soluzione
Non esiste un buon esempio di utilizzo dei registri quando si usano compilatori moderni (leggi: ultimi 15+ anni) perché non fa quasi mai del bene e può fare del male. Quando usi il registro, stai dicendo al compilatore " So come ottimizzare il mio codice meglio di te " che non è quasi mai il caso. Una delle tre cose che possono accadere quando si utilizza register:
- Il compilatore lo ignora, molto probabilmente. In questo caso l'unico danno è che non puoi prendere l'indirizzo della variabile nel codice.
- Il compilatore risponde alla tua richiesta e, di conseguenza, il codice funziona più lentamente.
- Il compilatore onora la tua richiesta e il codice viene eseguito più velocemente, questo è lo scenario meno probabile.
Anche se un compilatore produce un codice migliore quando si utilizza register, non c'è motivo di credere che un altro faccia lo stesso. Se disponi di un codice critico che il compilatore non sta ottimizzando abbastanza bene, probabilmente la soluzione migliore è probabilmente utilizzare l'assemblatore per quella parte, ma ovviamente fare la profilazione appropriata per verificare che il codice generato sia davvero un problema prima.
Altri suggerimenti
In generale, sono d'accordo con Robert , ma come ogni buona regola anche questa ha delle eccezioni.
Se stai lavorando su un sistema profondamente incorporato, potresti conoscere meglio del compilatore come ottimizzare il codice per la tua specifica applicazione sulla tua specifica architettura hardware .
Ma nel 99% dei casi la spiegazione di Roberts è valida anche per le parole incorporate.
So che è da un po 'di tempo, ma ecco un'implementazione di una sottoprocedura di heapsort in cui l'uso delle variabili di registro rende più veloce l'algoritmo, almeno usando gcc 4.5.2 per compilare il codice
inline void max_heapify(int *H, int i){
char OK = FALSE;
register int l, r, max, hI;
while(!OK){
OK = TRUE;
l = left(i);
r = right(i);
max = i;
if(l <= H[SIZE] && H[l] > H[i]){
max = l;
}
if(r <= H[SIZE] && H[r] > H[max]){
max = r;
}
if(max != i){
OK = FALSE;
hI = H[i];
H[i] = H[max];
H[max] = hI;
i = max;
}
}
}
Ho testato l'algortihm con e senza la parola chiave register prima degli attributi e l'ho eseguito per ordinare un array casuale con 50.000.000 di elementi sul mio notebook, alcune volte per ogni versione.
l'uso dei registri ha ridotto il tempo di heapsort da ~ 135s a ~ 125s.
Ho anche provato solo con 5.000.000 di elementi, ma l'ho eseguito più volte.
La versione senza registro è iniziata alle 11 ma ogni esecuzione ha ridotto il tempo fino a quando non ha raggiunto 9,65 secondi e si è fermata su di essa
la versione con il registro è iniziata alle 10 e ha ridotto il tempo fino alle 8,80.
Penso che abbia qualcosa a che fare con la memoria cache. Tuttavia sembra che i registri rendano l'algoritmo più veloce di un fattore costante
Dato che queste variabili sono abbastanza usate lungo l'algoritmo, assicurandosi che siano nel registro invece di lasciare questo lavoro al compilatore ha portato a un risultato migliore in questo caso. Tuttavia, il tempo non è migliorato così tanto.
Speriamo che il brivido sia utile a qualcuno, saluti.
Un altro caso comune è quando si implementano interpreti di basso livello. Mantenere un certo stato nei registri, ad es. puntatore dello stack della macchina virtuale, può ridurre significativamente l'accesso alla memoria e velocizzare il tuo codice.
Bene, questa è una domanda che ha bisogno di risposte multiple perché ci sono più contesti di codifica: dal punto di vista linguistico di alto livello, livello medio e basso (fino all'assemblaggio) poiché il linguaggio C può chiamare routine di assemblaggio.
Il motivo dell'utilizzo dell'assembly anziché di C è dovuto principalmente a problemi di prestazioni riscontrati durante lo sviluppo, quindi sì, è necessaria la parola chiave register ma no, in molti casi non funziona come previsto dallo sviluppatore