Die folgenden Tests wurden mit dem Visual C++ Compiler durchgeführt, wie er von der Standardinstallation von Qt Creator verwendet wird (ich vermute, ohne Optimierungsflag). Bei der Verwendung von GCC gibt es keinen großen Unterschied zwischen der Version von Mystical und meinem "optimierten" Code. Die Schlussfolgerung ist also, dass Compiler-Optimierungen sich besser um die Mikro-Optimierung kümmern als Menschen (letztendlich ich). Ich lasse den Rest meiner Antwort als Referenz stehen.
Es ist nicht effizient, Bilder auf diese Weise zu verarbeiten. Es ist besser, eindimensionale Arrays zu verwenden. Die Verarbeitung aller Pixel wird in einer Schleife durchgeführt. Der zufällige Zugriff auf Punkte könnte mit:
pointer + (x + y*width)*(sizeOfOnePixel)
In diesem speziellen Fall ist es besser, die Summe von drei Pixelgruppen horizontal zu berechnen und zwischenzuspeichern, da sie jeweils dreimal verwendet werden.
Ich habe einige Tests durchgeführt und denke, es lohnt sich, sie zu teilen. Jedes Ergebnis ist ein Durchschnitt von fünf Tests.
Originalcode von Benutzer1615209:
8193: 4392 ms
8192: 9570 ms
Die Version von Mystical:
8193: 2393 ms
8192: 2190 ms
Zwei Durchläufe mit einem 1D-Array: erster Durchlauf für horizontale Summen, zweiter Durchlauf für vertikale Summe und Durchschnitt. Adressierung in zwei Durchgängen mit drei Zeigern und nur Inkrementen wie hier:
imgPointer1 = &avg1[0][0];
imgPointer2 = &avg1[0][SIZE];
imgPointer3 = &avg1[0][SIZE+SIZE];
for(i=SIZE;i<totalSize-SIZE;i++){
resPointer[i]=(*(imgPointer1++)+*(imgPointer2++)+*(imgPointer3++))/9;
}
8193: 938 ms
8192: 974 ms
Zwei Durchgänge mit einem 1D-Array und einer Adressierung wie folgt:
for(i=SIZE;i<totalSize-SIZE;i++){
resPointer[i]=(hsumPointer[i-SIZE]+hsumPointer[i]+hsumPointer[i+SIZE])/9;
}
8193: 932 ms
8192: 925 ms
Horizontale Summen, die in einem Durchgang gecacht werden, sind nur eine Zeile voraus, damit sie im Cache bleiben:
// Horizontal sums for the first two lines
for(i=1;i<SIZE*2;i++){
hsumPointer[i]=imgPointer[i-1]+imgPointer[i]+imgPointer[i+1];
}
// Rest of the computation
for(;i<totalSize;i++){
// Compute horizontal sum for next line
hsumPointer[i]=imgPointer[i-1]+imgPointer[i]+imgPointer[i+1];
// Final result
resPointer[i-SIZE]=(hsumPointer[i-SIZE-SIZE]+hsumPointer[i-SIZE]+hsumPointer[i])/9;
}
8193: 599 ms
8192: 652 ms
Schlussfolgerung:
- Keine Vorteile der Verwendung mehrerer Zeiger und nur Inkremente (ich dachte, es wäre schneller gewesen)
- Das Zwischenspeichern horizontaler Summen ist besser, als sie mehrmals zu berechnen.
- Zwei Durchgänge sind nicht dreimal schneller, sondern nur zweimal.
- Mit einem einzigen Durchgang und der Zwischenspeicherung eines Zwischenergebnisses lässt sich eine 3,6-fache Geschwindigkeit erzielen.
Ich bin mir sicher, dass man es noch viel besser machen kann.
ANMERKUNG Bitte beachten Sie, dass ich diese Antwort geschrieben habe, um allgemeine Leistungsprobleme zu behandeln und nicht das Cache-Problem, das in der ausgezeichneten Antwort von Mystical erläutert wird. Am Anfang war es nur Pseudo-Code. In den Kommentaren wurde ich gebeten, Tests durchzuführen... Hier ist eine vollständig umgestaltete Version mit Tests.