Loop unrolling-Optimierung, wie funktioniert das
Betrachten dieser C-code:
int sum=0;
for(int i=0;i<5;i++)
sum+=i;
Könnte dies übersetzt werden in (pseudo-) Montage diese Weise (ohne loop unrolling):
% pseudo-code assembly
ADDI $R10, #0 % sum
ADDI $R11, #0 % i
LOOP:
ADD $R10, $R11
ADDI $R11, #1
BNE $R11, #5 LOOP
Also meine erste Frage ist, wie wird dieser code übersetzt mit loop unrolling, zwischen diesen beiden Möglichkeiten:
1)
ADDI $R10, #0
ADDI $R10, #0
ADDI $R10, #1
ADDI $R10, #2
ADDI $R10, #3
ADDI $R10, #4
2)
ADD $R10, #10
Ist der compiler optimieren den code und direkt wissen, dass es hat sich zu 10 addieren, ohne die Durchführung aller Summen?
Außerdem ist es eine Möglichkeit zu blockieren, die die pipeline mit einem Sprungbefehl? Muss ich das so geschrieben:
% pseudo-code assembly
ADDI $R10, #0 % sum
ADDI $R11, #0 % i
LOOP:
ADD $R10, $R11
ADDI $R11, #1
NOP % is this necessary to avoid the pipeline blocking?
NOP
NOP
NOP
BNE $R11, #5 LOOP
Zu vermeiden, dass die fetch-decode-exe-mem-write-back-Zyklus wird unterbrochen durch die Niederlassung?
- überprüfen Sie kompilierten code.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Diese ist eher zur demonstration, was ein compiler ist in der Lage, sondern als das, was alle compiler tun würde. Quelle:
Hinweis: die
printf
habe ich Hinzugefügt. Wenn die variable nicht verwendet, kann der compiler optimieren den gesamten loop.Kompilieren mit -O0 (Keine Optimierung)
gcc -Wall -O0 -S -c lala.c
:Der Schleife passiert, die in eine 'dumme' Art und Weise, mit
-8(%rbp)
variablei
.Kompilieren mit -O1 (Optimierung 1)
gcc -Wall -O1 -S -c lala.c
:Die Schleife wurde komplett entfernt und ersetzt mit dem entsprechenden Wert.
In abrollen, sucht der compiler um zu sehen, wie viele Iterationen passieren würde, und versucht zu entrollen durch ausführen weniger Iterationen. Zum Beispiel, die Schleife könnte dupliziert werden zweimal dazu führen würde, dass die Zahl der Geschäftsstellen halbiert werden. Solchen Fall in C:
Beachten Sie, dass eine iteration musste extrahiert werden aus der Schleife. Dies ist, weil 5 eine ungerade Zahl ist, und so kann die Arbeit nicht einfach halbiert werden, die durch das duplizieren des Inhalts. In diesem Fall wird die Schleife nur zweimal eingegeben werden. Der Assembler-code produziert von
-O0
:Komplett abrollen in C:
Dieser Zeit die Schleife wird tatsächlich nur einmal eingegeben. Die Montage produziert mit
-O0
:Diese Art der Optimierung ist in der Regel umgesetzt auf AST-Ebene anstatt der output-code (z.B. Montage) - Ebene. Loop unrolling kann getan werden, wenn die Anzahl der iteration behoben wird, und zur Kompilierzeit bekannt ist. So zum Beispiel habe ich diesen AST:
Würde der compiler ist bekannt, dass Für Start und Ende sind Konstanten, und daher konnte einfach kopieren Sie die Anweisungen, und ersetzen alle vorkommen von Var durch den Wert für jeden Aufruf. Oben, AST, wäre es übersetzt:
Ja, wenn es umgesetzt zu haben, eine solche Funktion. Es ist tatsächlich eine Verbesserung gegenüber den oben genannten Fall. In deinem Beispiel-Fall, nach dem abrollen, der compiler könnte erkennen, dass alle l-Wert bleibt der gleiche, während der r-Wert sind Konstanten. Daher könnte es führen peephole-Optimierung, verbunden mit constant folding Ausbeute single neben. Wenn die peephole-Optimierung ist auch der Auffassung, die Erklärung, dann könnte es noch optimiert mehr in einem einzigen move-Anweisung.
In der basic-Ebene, das Konzept der loop-unrolling ist, einfach kopieren den Körper der Schleife mehrfach als angemessen. Der compiler kann nicht, andere Optimierungen (z.B. das einfügen von festen Werten aus einer Berechnung) als gut, aber würde nicht als abrollen der Schleife, aber potenziell ersetzen Sie alle zusammen. Aber das wäre letztlich abhängig von den compiler-flags verwendet.
Dem C-code (ent -) nur wäre mehr wie folgt Aussehen:
Aber es gibt viele Möglichkeiten für den compiler, um noch weitere Optimierungen hier, dies ist nur ein Schritt.
sum
wäre die 0 am Ende. Ich glaube, Sie ging irgendwo falsch. Die Schleife wird nur einmal erfasst (was gut ist), aberi
ist nie erhöht.Gibt es keine generelle Antwort möglich, verschiedene Compiler, verschiedene Versionen von Ihnen, verschiedene compiler-flags variieren. Verwenden Sie die geeignete Compileroption zum Blick auf den assembler-Ergebnis. Mit gcc und verwandten dies ist die
-S
option.