2009-05-07 11 views
21

Ho una conoscenza generale di restrict ma spero di chiarire alcuni punti. Ho una funzione che legge una stringa con terminazione null da un buffer e scrive una versione con codifica URL in un altro buffer. La funzione ha questa firma (attualmente senza restrict):Quando utilizzare limit e quando non su

char const *StringUrlEncode(char const *unencoded, 
          char *encoded, 
          char *encodedEnd); 

unencoded è la mia stringa di origine terminazione null. Il buffer di destinazione è rappresentata da encoded e encodedEnd, dove encoded punta al primo char nel buffer e encodedEnd punti al primo carattere dopo il tampone, cioè la funzione scriverà char s fino a ma esclusione la posizione indicata a da encodedEnd - questa è la coppia di iteratori di base begin/end se si ha familiarità con le convenzioni STL di C++.

Se aggiungo restrict a questa funzione, dovrebbe essere applicato solo per i primi due parametri:

char const *StringUrlEncode(char const *restrict unencoded, 
          char *restrict encoded, 
          char *encodedEnd); 

o c'è qualche beneficio non ci sto capendo aggiungendolo a tutti e tre i parametri?

Vedo che rendere i buffer di input e output restrict aiuta il compilatore a sapere che non si sovrappongono. Ma dato che l'ultimo parametro, encodedEnd, è usato solo per segnare la fine del buffer di output, penso che lo restrict non sarebbe di alcun aiuto per il compilatore qui (anche se presumo che non danneggerebbe, oltre all'aggiunta rumore inutile alla dichiarazione di funzione).

risposta

12

Prova l'articolo di Mike Acton here. Limitare è spaventoso a causa sia delle implicazioni sul rendimento del non utilizzo che delle conseguenze dell'uso scorretto.

Nel tuo caso, sembra che tu possa applicare in modo sicuro dei limiti a tutti e tre i puntatori, poiché nessuno di essi ha la stessa area di memoria. Tuttavia non ci sarà alcun vantaggio in termini di prestazioni dall'usarlo sul terzo puntatore.

+1

Ho letto l'articolo di Mike (due volte) ed è un buon inizio, ma mi ha lasciato alcune domande :-) –

+1

Il collegamento fornito non è funzionale. Google suggerisce che è disponibile una versione aggiornata all'indirizzo http://cellperformance.beyond3d.com/articles/2006/05/demystifying-the-restrict-keyword.html (convalidato dal 2009-09-06), ma anche questo sta dando problemi. La versione cache è disponibile su Google. –

4

Penso che tu abbia ragione che non sarebbe male. Il puntatore del ciclo (chiamalo p) sarà uguale alla fine del ciclo. Ma non è necessario accedere a nulla dopo il ciclo (da p o encodedEnd), quindi non dovrebbe essere un problema. Non credo che sarà d'aiuto, perché niente è mai stato scritto o letto da encodeEnd quindi non c'è niente da ottimizzare.

Ma sono d'accordo con te che hai le prime due restrizioni che dovrebbero davvero aiutare.

+0

Si noti che la denoterizzazione codificataEnd è un comportamento indefinito poiché anche la codifica è limitata - quindi, in effetti, non importa se EncodedEnd è limitato o meno. – bdonlan

7

In questo caso particolare, non farà differenza se codificatoEnd è limitato o meno; hai promesso al compilatore che nessuno alias non codificato e codificato, e quindi le letture e le scritture non interferiranno tra loro.

La vera ragione che limitano è importante in questo caso è che senza di essa il compilatore non può sapere che scrive attraverso codificato non influirà legge attraverso non codificato.Ad esempio, se

encoded == unencoded+1 

quindi ogni scrittura codificati inciderebbe ogni successiva lettura dalla non codificato, quindi il compilatore non può programmare il carico fino a quando la scrittura è stata completata. limitare le promesse al compilatore che i due puntatori non influenzano la stessa memoria, in modo che possa pianificare i carichi abbastanza avanti per evitare stalli della pipeline.