Pour corriger, et recibler mon propos sur les GPUs.
On ne peut pas vraiment dire que leurs coeurs soient des processeurs.
Ils ont tous la même suite d'instructions, la même unité dont j'ai oublié le nom qui fournit le code de l'instruction à effectuer.
(Unité de contrôle je crois ? Je ne sais-plus
)
Mais les unités de calcul des GPU comportent (et travaillent sur), des registres 128 bits. Et des palettes de matrices 4x4, de flottants 32 bits.
Elles ont des unités de calcul (ALU) phénoménales, on peut tout leur demander : + - / *, sinus cosinus racine carré exponentielle, logarithme, puissance (entre 2 flottants), etc etc.
Et elles font ces calculs sur des vecteurs. (Plusieurs valeurs (4) à la fois).
On peut aussi faire du calcul sur des flottants de 64 bits (double en C et C++) Mais que 2 par 2.
Ensuite des librairies comme Cuda et OpenCl ont permis de programmer pour des matrices et des vecteurs de taille quelconque, et de faire des merveilles.
Les réseaux neuronaux sont les parfaits candidats pour ces librairies. Il ne risque pas d'y avoir des tests divergents
(il n'y a pas ce problème dans les calculs matriciels).
C'est pourquoi on utilise énormément les GPUs dans l'AI aujourd'hui.
Si on veut de nos jours faire du calcul matriciel intensif, c'est la meilleure solution.
Utiliser Cuda ou OpenCl.
Mais il semble exister des framework qui encapsulent encore mieux le processus. Programmables en Python.
Il y a un membre bcp plus qualifié que moi pour en parler.
Quand on compile un shader HLSL (DirectX) , on a le code en assembleur généré affiché en bonus. (En plus du code compilé sous forme de fichier binaire. Exécutable).
Cela est parfois indispensable pour optimiser son shader.
Car les shaders sont capricieux. Un seul mot de travers et on divise les performances par 10, si on l'avait codé autrement !
L'avantage des GPUs, c'est qu'ils ont tous le même jeu d'instructions. Même s'il s'enrichit avec les progrès, avec le temps.
Du coup un shader compilé est valable pour n'importe quel GPU.
J'avais parlé des tests incohérents (dont tous n'ont pas le même résultat), mais il y aussi les boucles.
Les boucles et les GPUs ne sont pas amis non plus.
(Ils sont chiants les GPUs !)
Il faut préciser combien il y a d'itérations au max dans une boucle, via la directive [unroll x], où x est le nombre maximal d'itérations.
Et le compilateur déploie la boucle en une suite d'instructions, sans boucle.
Ce n'est pas obligatoire, mais si on ne le fait pas, on peut s'attendre à une baisse de performance phénoménale !
Pour la même raison que pour les tests incohérents : les unités de calculs ne sont plus synchrones et s'attendent les unes les autres avant de passer à la prochaine instruction....
Les GPUs sont une bénédiction pour le calcul parallèle, mais une malédiction pour le calcul séquentiel.
Et il ne faut pas grand-chose pour briser leur harmonie de calculs parallèles.
Autre chose, on pourrait se demander pourquoi les meilleurs GPUs ne sont cadencés qu'aux alentours de 1 GHz. Alors que les CPUs sont vers 5GHz.
Car ce qui compte, c'est le nombre d'unités de calcul, et pas l'horloge. C'est du calcul parallèle.
Quand on augmente sur la superficie de la puce le nombre d'unités de calcul, on progresse de manière quadratique. (au carré).
Si on progressait juste sur la cadence, cela serait linéaire.
Il vaut mieux passer de 4 à 9 unités de calculs que de doubler la fréquence d'horloge. (Exemple théorique).