| ||||||||
Nous allons enfin utiliser toute la puissance de notre ordinateur (enfin presque toute). Mais la vectorisation ne se fait pas toute seule. Nous allons utiliser l'option de gcc qui permet de vectoriser le programme, mais il va falloir que nous modifions un peut notre fonction. Le compilateur est très prudent en ce qui concerne la vectorisation, en gros, si vous ne lui définissez pas tout bien comme il faut, vous pourrez mettre toutes les options de vectorisation que vous voudrez il n'en aura rien à faire. Nous devons garantir deux choses :
Pour le premier point, nous allons utiliser le mot clé __restrict__ qui permet de dire au compilateur que les pointeurs pointent vers des tableaux indépendants qui ne se recouvrent pas (Bien sûr, si vous lui mentez, ça va mal se passer). Nous allons créer une nouvelle fonction donc le prototype sera le suivant :
Notez que les variables n'ont plus les mêmes noms, mais la encore, c'est de la cosmétique. Pour garantir le deuxième point, nous allons utiliser la fonction __builtin_assume_aligned, qui créer un pointeur aligné à partir d'un pointeur et d'un alignement donné. Voici l'implémentation de cette nouvelle fonction :
Si vous appelez cette fonction dans le main, sans modifier les options de compilation, vous obtiendrez quand même un gain : ./optimisationsgemm 2.326441 cy/fma Nous étions précédemment à 2.926861 cy/fma, nous avons encore gagner un peu (21 pour-cents). C'est tout à fait normal car les données son mieux alignées et on garanti qu'elle sont indépendantes. Changeons les options de compilation :
par :
Ce qui nous donne, après re-compilation : ./optimisationsgemm 1.086403 cy/fma Nous étions à 2.326441 cy/fma, nous avons donc gagner 54 pour-cents ce qui est énorme. Nous pouvons maintenant avoir un calcul à chaque cycle. Et si je le relance, c'est encore mieux : ./optimisationsgemm 1.046540 cy/fma On est toujours au alentour d'un calcul par cycle ce qui est bien. | ||||||||
|