restrânge
Cuvânt cheie restrict
este utilizat în limbajul C (începând cu standardul C99) pentru a se califica un indicator ca să nu fac obiectul aliasing de alte indicii care nu sunt declarate de la ea. În declararea unui indicator de restrict
, programatorul face o declarație de intenție, informând compilatorul că, în întregul său ciclu de viață, doar acel indicator și eventual alți indicatori derivați din acesta vor fi folosiți pentru a accesa obiectul ascuțit. Dacă declarația de intenție este încălcată de programator și un alt indicator este utilizat pentru a accesa obiectul, comportamentul programului este nedefinit .
Aceste informații permit compilatorului să genereze un cod mai bine optimizat: în principiu, adăugarea de restrict
la standardul C face posibilă reducerea decalajului cu Fortran în aplicațiile de calcul numeric . [1]
Standardul de limbaj C ++ nu include cuvântul cheie restrict
, dar mulți compilatori implementează un cuvânt cheie nestandard care oferă un efect similar omologului său C, cum ar fi __restrict__
în GCC [2] sau __restrict
și __declspec(restrict)
în Visual C ++ . [3]
Optimizare
Dacă compilatorul este sigur că doar un pointer poate accesa un bloc de memorie, este posibil să se genereze un cod mai bine optimizat, de exemplu prin schimbarea ordinii instrucțiunilor pentru a efectua toate operațiile de load
sau store
consecutiv sau evitând încărcarea unuia valoare (știind că nu poate fi modificată printr-un alt indicator de restrict
). De exemplu, având în vedere funcția
void updatePtrs (size_t * PTRA, size_t * ptrB, size_t * val)
{
* ptrA + = * val ;
* ptrB + = * val ;
}
indicatorii ptrA
, ptrB
și val
ar putea accesa aceeași regiune de memorie ( aliasing pointer ), astfel încât compilatorul trebuie să ia în considerare această posibilitate atunci când generează codul mașinii. De exemplu, gcc -O3 -S
(folosind versiunea gcc 8.2) generează următorul ansamblu x86-64 pentru corpul funcției
movq (% RDX),% rax
addq% rax, (% DZR)
movq (% RDX),% rax
addq% rax, (% rsi)
ret
Dacă aliasarea este exclusă, calificarea indicatoarelor ca restrict
în declarație
updatePtrs nule (size_t * restricționa PTRA, size_t * restricționa ptrB, size_t * restricționați val);
compilatorul poate presupune în mod legitim că ptrA
, ptrB
și val
vor accesa întotdeauna regiuni de memorie care nu se suprapun și operațiunile efectuate printr-un pointer nu vor avea niciun efect asupra obiectelor la care se referă alți indicatori (este totuși responsabilitatea programatorului să garanteze acest fapt în scris cod). Acest lucru face inutilă citirea din nou a valorii indicate de val
după executarea primei instrucțiuni, iar ansamblul devine
movq (% RDX),% rax
addq% rax, (% DZR)
addq% rax, (% rsi)
ret
Notă
- ^ Ulrich Drepper , Memoria partea 5: Ce pot face programatorii , în Ce ar trebui să știe fiecare programator despre memorie , lwn.net , 23 octombrie 2007.
«" ... Regulile implicite de aliasing ale limbajelor C și C ++ nu ajută compilatorul să ia aceste decizii (dacă nu se folosește restricție, toate accesele pointerului sunt surse potențiale de aliasing). Acesta este motivul pentru care Fortran este încă un limbaj preferat pentru programarea numerică: facilitează scrierea unui cod rapid. (În teorie, cuvântul cheie restricționat introdus în limbajul C în revizuirea din 1999 ar trebui să rezolve problema. Compilatoarele nu au ajuns încă din urmă. Motivul este în principal faptul că prea mult este incorect există un cod care ar induce în eroare compilatorul și ar determina generarea unui cod obiect incorect.) "» . - ^ Folosind colecția GNU Compiler: Restricted Pointers , la gcc.gnu.org .
- ^ __restrict , pe msdn.microsoft.com .
Bibliografie
- ISO / IEC 9899: Proiectul comitetului TC2 ( PDF ), ISO , 6 mai 2005, pp. 108-112. Adus 22/12/2008 .
linkuri externe
- Demistificarea cuvântului cheie restricționat : explicație și exemple de utilizare
- Douglas Walls, Cum se utilizează restricția de calificare în C , la oracle.com , Oracle ™. Adus pe 21 noiembrie 2012 .
- Indicatori restricționați în C : rațiunea inițială din spatele definiției