4.3.1 : Comment rendre vectorisable notre calcul ?



C'est souvent la question l'a plus importante (une fois que l'on a réglé toutes les autres, I/O, formats de données, algorithmes, etc.).

Nottons que les possibilité d'avoir un résultat plus rapidement sont grandes sans se cassez la tête avec des fonctions intrinsèques :



Ici, on veut quand même se mettre dans un cas où on ne va pas ratiboiser la précision du calcul pour gagner du temps. Du genre, on augmente suffisament l'intervalle de temps, on vire les images intermédiares et on gagne un facteur 35. Il est bien d'avoir ces idées en tête mais ce n'est pas le propos du moment...


La question est : que faire lorsque l'on est face à un mur et que même le compilateur n'arrive pas à nous aider ?

Réponse : on fait exploser le mur et on aide le compilateur notej'aime bien la pyrotechnie..

Si on résume la situation, le compilateur n'arrive pas a vectoriser correctement car les valeurs que l'on traite sont :

Dans les deux cas la vectorisation va mal se passer.

Le problème est donc :

Comment faire pour que les valeurs dans un registre vectoriel soient toutes voisines de celles dans le registre vectoiel voisin du premier ?

Si nos registres vectoriels sont de taille N, une méthode, un peu bourin certes, pourrait être de calculer N réactions en même temps avec N conditions initiales. C'est bien d'y penser mais on va consommer N fois plus de mémoire et ça ne nous arrange pas si on veut optimiser un seul calcul.

Il faut que nous construisions une matrice où chaque vecteur de N valeurs à des vecteurs voisins qui contiennent les valeurs voisines du précédent.

La figure 6 montre comment modifier une matrice pour satisfaire cette condition pour des registres vecotriels de 4 éléments.

Figure 6 : Comment réordonner les valeurs d'une matrice $16\times 6$ pour que chaque vecteur de $4$ élements contiennent les voisins de ses voisins.



Donc, pour utiliser une vectorisation de taille N dans notre matrice de départ:



Dans notre cas, la valeur 0 est une valeur dite de padding. Nous utilisons 0 qui est une valeur neutre pour la multiplication, l'addition et la soustraction. Mais dans le cas d'un calcul utilisant une division, nous utiliseront plutôt la valeur 1 comme padding qui est neutre pour la division.


Cette méthode est un peut bancale si la matrice a moins de N lignes et d'une manière générale elle sera très efficace sur une matrice qui a beaucoup de lignes car le coût de synchronisation de la première et de la dernière ligne sera proportionnellement plus faible.