Les tests suivants ont été effectués avec le compilateur Visual C ++ car il est utilisé par l'installation par défaut de Qt Creator (je suppose sans indicateur d'optimisation). Lors de l'utilisation de GCC, il n'y a pas de grande différence entre la version de Mystical et mon code "optimisé". La conclusion est donc que les optimisations du compilateur prennent mieux soin de la micro-optimisation que les humains (moi enfin). Je laisse le reste de ma réponse pour référence.
Il n'est pas efficace de traiter les images de cette façon. Il est préférable d'utiliser des tableaux à une dimension. Le traitement de tous les pixels se fait en une seule boucle. L'accès aléatoire aux points pourrait se faire en utilisant:
pointer + (x + y*width)*(sizeOfOnePixel)
Dans ce cas particulier, il est préférable de calculer et de mettre en cache la somme de trois groupes de pixels horizontalement car ils sont utilisés trois fois chacun.
J'ai fait quelques tests et je pense que cela vaut la peine d'être partagé. Chaque résultat est une moyenne de cinq tests.
Code original par user1615209:
8193: 4392 ms
8192: 9570 ms
Version de Mystical:
8193: 2393 ms
8192: 2190 ms
Deux passes en utilisant un tableau 1D: première passe pour les sommes horizontales, seconde pour la somme verticale et moyenne. Adressage en deux passes avec trois pointeurs et uniquement des incréments comme celui-ci:
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
Deux passes en utilisant un tableau 1D et un adressage comme celui-ci:
for(i=SIZE;i<totalSize-SIZE;i++){
resPointer[i]=(hsumPointer[i-SIZE]+hsumPointer[i]+hsumPointer[i+SIZE])/9;
}
8193: 932 ms
8192: 925 ms
Une passe de mise en cache des sommes horizontales juste une ligne en avant pour qu'elles restent en cache:
// 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
Conclusion:
- Aucun avantage d'utiliser plusieurs pointeurs et juste des incréments (je pensais que cela aurait été plus rapide)
- Il est préférable de mettre en cache des sommes horizontales que de les calculer plusieurs fois.
- Deux passes ne sont pas trois fois plus rapides, deux fois seulement.
- Il est possible d'obtenir 3,6 fois plus rapidement en utilisant à la fois un seul passage et la mise en cache d'un résultat intermédiaire
Je suis sûr qu'il est possible de faire beaucoup mieux.
REMARQUE
Veuillez noter que j'ai écrit cette réponse pour cibler les problèmes de performances généraux plutôt que le problème de cache expliqué dans l'excellente réponse de Mystical. Au début, c'était juste un pseudo-code. On m'a demandé de faire des tests dans les commentaires ... Voici une version complètement refactorisée avec des tests.