„Loop unrolling“ – Versionsunterschied
| [gesichtete Version] | [gesichtete Version] |
K Änderung 106767179 von Plankton314 wurde rückgängig gemacht. Bitte genauer hinschauen: Im Schleifenkopf steht nicht die Anzahl der Durchläufe, sondern eine Obergrenze für i. |
K Beschreibung ergänzt |
||
| Zeile 23: | Zeile 23: | ||
* es müssen Kontrollanweisungen eingefügt werden um eine nur teilweise entrollte Schleife korrekt auszuführen. |
* es müssen Kontrollanweisungen eingefügt werden um eine nur teilweise entrollte Schleife korrekt auszuführen. |
||
Die Schleife kann nur teilweise entrollt werden, bspw. wenn sie sehr oft durchlaufen werden muss oder die genaue Anzahl der Durchläufe unbekannt ist |
Die Schleife kann nur teilweise entrollt werden, bspw. wenn sie sehr oft durchlaufen werden muss oder die genaue Anzahl der Durchläufe unbekannt ist. |
||
Ein einzelner „Abroll“-Schritt verdoppelt die Anzahl der Kopierbefehle im Schleifenrumpf, dadurch halbiert sich die Anzahl der Durchläufe und damit auch die der Vergleiche: |
|||
<source lang="cpp"> |
<source lang="cpp"> |
||
Version vom 13. August 2012, 16:53 Uhr
Loop unrolling ist eine Optimierung, die die Laufzeit eines Programms beschleunigt, auf Kosten seiner Größe.[1]
Dabei wird versucht, Schleifen derart umzuwandeln, dass die Schleifenbedingungen seltener oder gar nicht mehr überprüft werden. Im Idealfall entfallen dadurch auch die Zählvariablen.
Moderne Compiler Entrollen Schleifen bei Bedarf automatisch, so dass diese Technik nicht mehr von Hand angewandt werden muss.[2]
Idee
Bei einer Schleife muss in jedem Durchlauf die sogenannte Schleifenbedingung geprüft werden. Gerade bei Schleifen mit sehr kleinen Rumpf kann diese Prüfung einen verhältnismäßig großen Anteil der Laufzeit ausmachen.
for (int i=0; i<8; ++i)
dest[i] = src[i];
Eine solche Schleife besteht nur aus wenigen Anweisungen: Kopieren, Erhöhen des Zählers, Prüfen der Bedingung und Sprung. Somit verbringt der Prozessor etwa die Hälfte der Zeit nur mit Kontrollanweisungen.[3]
Die naheliegende Lösung ist, mehr Anweisungen in den Schleifenrumpf zu packen. Dadurch sinkt die Anzahl der ausgeführten Kontrollanweisungen.
Damit ein Compiler eine Schleife entrollen kann, muss
- die Anzahl der Schleifendurchläufe bereits bei der Übersetzung bekannt sein oder
- es müssen Kontrollanweisungen eingefügt werden um eine nur teilweise entrollte Schleife korrekt auszuführen.
Die Schleife kann nur teilweise entrollt werden, bspw. wenn sie sehr oft durchlaufen werden muss oder die genaue Anzahl der Durchläufe unbekannt ist.
Ein einzelner „Abroll“-Schritt verdoppelt die Anzahl der Kopierbefehle im Schleifenrumpf, dadurch halbiert sich die Anzahl der Durchläufe und damit auch die der Vergleiche:
for (int i=0; i<8; ++i) {
dest[i] = src[i];
++i;
dest[i] = src[i];
}
Oder auch vollständig:
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
dest[4] = src[4];
dest[5] = src[5];
dest[6] = src[6];
dest[7] = src[7];
Vorteile
- Die Ausführungszeit verkürzt sich, da weniger Kontrollanweisungen ausgeführt werden.
- Wenn die Schleife komplett entrollt werden kann, entfällt das Zählen und die zugehörigen Variablen.
- Besseres Pipelining.
- Weniger Branches im Programmablauf.
Nachteile
- Die Größe des Programms wächst, da die Anzahl der Instruktionen steigt.
- Beim manuellen Entrollen verschlechtert sich die Lesbarkeit des Quelltextes.
Siehe auch
Einzelnachweise
- ↑ Ullman, Jeffrey D.; Aho, Alfred V.: Principles of compiler design, Addison-Wesley, 1977, ISBN 0-201-10073-8
- ↑ Intel C++ Compiler User and Reference Documentation
- ↑ Referenzfehler: Ungültiges
<ref>-Tag; kein Text angegeben für Einzelnachweis mit dem Namen duff83.