Comment rendre ce code plus rapide (apprendre les meilleures pratiques)?

J’ai cette petite boucle ici, et je me demandais si je faisais une grosse erreur, sage.

Par exemple, existe-t-il un moyen de réécrire certaines parties différemment, afin de rendre la vectorisation possible (en supposant que GCC4.8.1 et tous les indicateurs favorables à la vecosortingzation soient activés)?

Est-ce le meilleur moyen de transmettre à une liste un nombre (const float name_of_var [])?

L’idée du code est de prendre un vecteur (au sens mathématique, pas nécessairement un std :: vecteur) de (nombres non sortingés) y et deux valeurs liées ( ox[0]<=ox[1] ) et de le stocker dans un vecteur d’entiers rdx l’indice i de l’entrée de y satisfaisant ox [0] <= y [i] <= ox [1].

rdx peut contenir m éléments et y a la capacité n et n>m . S’il y a plus de m valeurs de y[i] satisfaisant ox [0] <= y [i] <= ox [1], le code devrait alors renvoyer le premier m

Merci d’avance,

 void foo(const int n,const int m,const float y[],const float ox[],int rdx[]){ int d0,j=0,i=0; for(;;){ i++; d0=((y[i]>=ox[0])+(y[i]<=ox[1]))/2; if(d0==1){ rdx[j]=i; j++; } if(j==m) break; if(i==n-1) break; } } 

 d0=((y[i]>=ox[0])+(y[i]<=ox[1]))/2; if(d0==1) 

Je crois que l’utilisation d’une variable intermédiaire est inutile et prend quelques cycles de plus

C'est la version la plus optimisée à laquelle je puisse penser, mais elle est totalement illisible ...

 void foo(int n, int m, float y[],const float ox[],int rdx[]) { for(int i = 0; i < n && m != 0; i++) { if(*y >= *ox && *y <= ox[1]) { *rdx=i; rdx++; m--; } y++; } } 

Je pense que la version suivante avec un indicateur d'optimisation décent devrait faire l'affaire

 void foo(int n, int m,const float y[],const float ox[],int rdx[]) { for(int j = 0, i = 0; j < m && i < n; i++) //Reorder to put the condition with the highest probability to fail first { if(y[i] >= ox[0] && y[i] <= ox[1]) { rdx[j++] = i; } } } 

Juste pour m’assurer que j’ai raison: vous essayez de trouver les premières valeurs m + 1 (s’il s’agit en fait de m, est-ce que j == m-1) se situent dans la plage de [ox [0], ox [1 ]]?

Si oui, ne serait-il pas préférable de faire:

 for (int i=0, j=0;;++i) { if (y[i] < ox[0]) continue; if (y[i] > ox[1]) continue; rdx[j] = i; j++; if (j == m || i == n-1) break; } 
  1. Si y [i] est effectivement dans la plage, vous devez effectuer les deux comparaisons comme nous le faisons tous les deux.
  2. Si y [i] est sous ox [0], il n’est pas nécessaire d’effectuer la deuxième comparaison.
  3. J’évite l’utilisation de la division.

R. Oui, passer le tableau float en tant que float [] n’est pas seulement efficace, c’est le seul moyen (et est identique à un argument float *).

A1. Mais en C ++, vous pouvez utiliser de meilleurs types sans perte de performance. L’access à un vecteur ou à un tableau (le conteneur de bibliothèque standard) ne doit pas être plus lent qu’à l’access à un tableau de style C. Je vous conseillerais fortement de les utiliser. En C ++ moderne, il est également possible d’utiliser des iterators et des foncteurs; Je ne suis pas un expert dans ce domaine, mais si vous pouvez exprimer l’indépendance des opérations sur différents éléments en étant plus abstrait, vous pouvez donner au compilateur la possibilité de générer un code plus adapté à la vectorisation.

B. Vous devez remplacer la division par un ET logique, opérateur &&. Le premier avantage est que la deuxième condition n’est pas du tout évaluée si la première est fausse – ceci pourrait être votre gain de performance le plus important ici. Le deuxième avantage est l’expressivité et donc la lisibilité.

C. La variable intermédiaire d0 disparaîtra probablement lors de la compilation avec -O3, mais elle n’est néanmoins pas nécessaire.

Le rest est correct en termes de performances. Idiomatiquement, des améliorations sont possibles, comme cela a déjà été démontré.

D. Je ne suis pas sûr d’une chance de vectorisation avec le code présenté ici. Le compilateur effectuera probablement une boucle en déroulant à -O3; essayez de le laisser émettre du code SSE (cf. http://gcc.gnu.org/onlinedocs/ , plus précisément http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/i386-and-x86- 64-Options.html # i386-and-x86-64-Options ). Qui sait.

Oh, je viens de me rendre compte que votre code d’origine passe les limites d’intervalle constant sous la forme d’un tableau à 2 éléments, ox []. Étant donné que l’access à la masortingce est une indirection inutile et qu’en tant que tel peut entraîner une surcharge, l’utilisation de deux parameters float normaux serait préférable ici. Gardez-les comme votre tableau. Vous pouvez également les nommer bien.