Maître de Conférences en Informatique à l'Université d'Angers
Ce site est en cours de reconstruction certains liens peuvent ne pas fonctionner ou certaines images peuvent ne pas s'afficher.
Créer un exécutable (dot_product.exe) en architecture 32 bits qui permet de calculer le produit scalaire de deux vecteurs de floats en utilisant les méthodes suivantes :
On rappelle que le produit scalaire de deux vecteurs est calculé par :
$$ ps(x,y) = ∑↙{i=0}↖{n-1} x_i × y_i $$Le programme sera composé de codes sources en C++ et en assembleur :
Le programme devra prendre en entrée 3 paramètres :
| Description | Variable | Option (getopt) |
|---|---|---|
| nombre de répétitions du calcul | zillions | -z entier |
| taille des vecteurs de réels | vector_size | -s entier |
| méthode de calcul utilisée | method | -m entier |
On utilisera deux vecteurs de floats dont la taille sera multiple de 8 (car nous utiliserons la technologie vectorielle AVX) et qui seront alloués dynamiquement en utilisant _mm_malloc ou posix_memalign.
On calculera le nombre de cycles CPU utilisés par chaque version en utilisant la classe CPUTimer qui se compose de 2 fichiers :
Note : on peut également mesurer le temps en utilisant la librairie chrono du C++11 :
Voici le code introductif du programme :
Ecrire la méthode dp_fpu qui réalise le calcul du produit scalaire en utilisant la FPU et l'intégrer au programme. Pour cela on utilisera les instructions :
Afin de coder la méthode dp_ref du listing précédent, on utilisera les conventions suivantes :
Mettre au point un makefile afin d'automatiser la compilation. On doit notamment prendre en compte lors de l'édition de liens les fichiers objets suivants :
Comme on va utiliser les instructions SSE dans leur version intrinsics plus tard, il est nécessaire d'utiliser l'option de compilation -msse4.2 de gcc/g++.
Ecrire la méthode dp_sse_low qui réalise le calcul du produit scalaire en utilisant les 32 premiers bits du vecteur SSE xmm0 qui représentera la variable sum. Utiliser dans ce cas les instructions :
A la fin du calcul il faut placer la partie basse de xmm0 dans st0 puisque la convention d'appel du C en 32 bits impose que le résultat soit placé dans st0. Pour cela, on réserve de l'espace mémoire dans la pile en abaissant le sommet de pile de 4 octets. On oubliera pas, après le transfert de la donnée, de remonter le sommet de pile de 4 octets.
Ecrire la méthode dp_sse_vec qui réalise le calcul du produit scalaire en utilisant $4 × 32$ bits d'un vecteur SSE. Vous pouvez utiliser :
Le code équivalent en C doit ressembler à :
Les instructions SSE à utiliser sont les suivantes :
Ecrire la méthode dp_avx_vec qui réalise le calcul du produit scalaire en utilisant $8 × 32$ bits d'un vecteur AVX. Utiliser dans ce cas les instructions :
Ecrire une version intrinsics dp_sse_intrin qui sera traduite par le compilateur C++. On utilisera le site Intel Intrinsics Guide afin d'obtenir une correspondance entre instructions assembleur et méthodes intrinsics.