Poniższe testy zostały wykonane przy użyciu kompilatora Visual C ++, ponieważ jest on używany przez domyślną instalację Qt Creator (chyba bez flagi optymalizacji). Podczas korzystania z GCC nie ma dużej różnicy między wersją Mystical a moim „zoptymalizowanym” kodem. Wniosek jest taki, że optymalizacje kompilatora lepiej zapobiegają mikrooptymalizacji niż ludzie (w końcu ja). Resztę mojej odpowiedzi zostawiam w celach informacyjnych.
Przetwarzanie obrazów w ten sposób nie jest wydajne. Lepiej jest używać tablic jednowymiarowych. Przetwarzanie wszystkich pikseli odbywa się w jednej pętli. Losowy dostęp do punktów można uzyskać za pomocą:
pointer + (x + y*width)*(sizeOfOnePixel)
W tym konkretnym przypadku lepiej jest obliczyć i buforować sumę trzech grup pikseli w poziomie, ponieważ są one używane trzy razy.
Zrobiłem kilka testów i myślę, że warto się tym podzielić. Każdy wynik to średnio pięć testów.
Oryginalny kod użytkownika1615209:
8193: 4392 ms
8192: 9570 ms
Wersja Mystical:
8193: 2393 ms
8192: 2190 ms
Dwa przejścia przy użyciu tablicy 1D: pierwsze przejście dla sum poziomych, drugie dla sumy pionowej i średniej. Adresowanie dwuprzebiegowe z trzema wskaźnikami i tylko takie przyrosty:
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
Dwa przejścia za pomocą tablicy 1D i adresowania w ten sposób:
for(i=SIZE;i<totalSize-SIZE;i++){
resPointer[i]=(hsumPointer[i-SIZE]+hsumPointer[i]+hsumPointer[i+SIZE])/9;
}
8193: 932 ms
8192: 925 ms
Jedno przejście buforuje poziome sumy tylko o jeden rząd do przodu, aby pozostały w pamięci podręcznej:
// 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
Wniosek:
- Brak korzyści z używania kilku wskaźników i tylko przyrosty (myślałem, że byłoby szybciej)
- Buforowanie sum poziomych jest lepsze niż ich wielokrotne obliczanie.
- Dwa podania nie są trzy razy szybsze, tylko dwa razy.
- Możliwe jest osiągnięcie 3,6 razy szybciej przy użyciu zarówno pojedynczego przejścia, jak i buforowania wyniku pośredniego
Jestem pewien, że można zrobić znacznie lepiej.
UWAGA
Należy pamiętać, że napisałem tę odpowiedź, aby rozwiązać ogólne problemy z wydajnością, a nie problem z pamięcią podręczną wyjaśniony w doskonałej odpowiedzi Mystical. Na początku był to tylko pseudo kod. Zostałem poproszony o wykonanie testów w komentarzach ... Oto całkowicie przebudowana wersja z testami.