Nvidia GeForce GTX 750 Ti & GTX 750 : Maxwell fait ses débuts

Publié le 26/02/2014 par
Imprimer
GPU computing : des petites retouches qui font la différence
Après avoir atteint une limite thermique avec Fermi, Nvidia a fait le choix de donner la priorité à l'efficacité énergétique. Des travaux d'optimisation qui ont posé les bases de Kepler et nous ont amenés vers Maxwell. Un choix qui a entraîné des compromis, notamment une rationalisation des possibilités offertes au GPU computing.

A l'inverse, AMD a mis en place une architecture GCN très flexible à ce niveau, ce qui lui a permis par exemple d'être très performante dans le cadre des algorithmes liés aux crypto-monnaies (Litecoin etc.). Ce n'était pas un choix spécifique d'AMD de viser cet usage potentiel, mais une heureuse incidence de ses choix de flexibilité.

Dans ce même domaine, les GPU Kepler souffrent, Nvidia n'ayant pas pris en compte cet usage lors du design de son architecture. Mais progressivement, l'architecture de ses GPU reçoit de petites retouches plus ou moins spécifiques pour "débloquer" des situations jugées importantes. C'est de toute évidence le cas des crypto-monnaies (mais en fait de tout ce qui est cryptage en général). Voici en résumé les améliorations :

- augmentation du débit des opérations logiques et sur les entiers
- réduction de la latence des unités de calcul
- possibilité d'utiliser plus de 63 registres par thread (jusqu'à 255)
- la mémoire partagée totale passe de 48 à 64 Ko par SMM
- le texture cache peut faire office de L1D comme sur le GK110
- support du Dynamic Parallelism comme sur le GK110

Nous avons pu réaliser quelques tests synthétiques avec différents outils, dont ceux de SiSoft Sandra, et observer de nets gains (x2, x3, x5!) dans certains cas, notamment dans certains algorithmes liés aux crypto-monnaies. Rien ne nous garantit cependant que l'optimisation de ces algorithmes est poussée de la même manière pour toutes les architectures et il est difficile d'en tirer des conclusions si ce n'est qu'il semble bel et bien qu'il y ait une amélioration importante en pratique dans certains domaines.

Notez également à ce sujet que Sandra met en avant une réduction significative de la latence mémoire, mais sans contrôle sur ce test il est difficile de savoir ce qu'elle représente et ces résultats pourraient être mal interprétés. Contrairement à un CPU, un GPU est conçu pour masquer de fortes latences et travaille de manière à le faire. Quand un logiciel montre une latence en baisse, cela ne veut pas dire obligatoirement qu'il y a une amélioration des caches ou de l'interface mémoire, mais peut être simplement que pour une raison x ou y le GPU s'est préparé à masquer une latence moindre.


Plus en détails pour les plus courageux
Nvidia nous a expliqué avoir boosté significativement le débit de certaines opérations logiques et sur les entiers. Par exemple, les multiplications 32-bit (et MAD) sur les entiers étaient traitées avec un débit équivalent à la moitié de celui des calculs flottants sur Fermi mais était tombé à 1/6ème sur Kepler, soit 32 par cycle par SMX. Nvidia ne spécifie pas le débit sur Maxwell mais indique qu'il est plus élevé. La seule possibilité logique semble être de passer le SMM de 32 à 64 multiplication entières par cycle soit un débit de 1/2, comme sur Fermi.

Nvidia précise avoir également accéléré certaines instructions de type shift (comme le funnel shift), très utiles aux crypto-monnaies et avoir ajouté de nouvelles instructions spécifiques pour accélérer les opérations arithmétiques sur les pointeurs.

Toujours sur le plan des unités de calcul, Nvidia a revu leur latence à la baisse (soit la longueur du pipeline qu'elles représentent), mais ne communique pas de valeur précise. Pour rappel, les unités de calcul des GPU Nvidia depuis Kepler travaillent sur des vecteurs de 32 éléments ou threads appelés warps (contre 64 éléments appelés wavefronts du côté d'AMD). Les SIMD 32-way ont un débit d'une opération FP32 par cycle, exécutée simultanément sur les 32 threads qui composent le warp, mais la latence est plus élevée, elle est de 11 cycles sur Kepler. L'ordonnanceur jongle entre plusieurs warps pour masquer cette latence et en la réduisant sur Maxwell, Nvidia réduit le nombre d'éléments qui doivent résider dans le SMM pour maintenir le débit maximal de celui-ci. Il fallait par exemple au minimum 352 pixels ou threads, organisés en 11 groupes de 32 (les warps) par partition de SMX Kepler pour exploiter ses unités de calcul à pleine vitesse, et il en faudra moins dans un SMM.

Etant donné que la taille des différents caches présents dans le SMM reste identique à ceux du SMX, cela signifie que leur disponibilité par élément pourra augmenter dans certains cas. Par exemple, le fichier registres de 64 Ko par partition correspond à 16384 registres 32-bit ou 512 entrées de 1024-bit (largeur des SIMD 32-way) que doivent se partager les différents warps qui résident dans le SMX/SMM. Moins il y en a, plus grosse est la part du gâteau. Sur Kepler, avec 11 cycles de latence, le nombre maximal de registres 32-bit par thread pour autoriser une puissance de calcul maximale est de 46. C'est un peu plus élevé sur Maxwell. Par ailleurs comme sur le GK110, mais cette fois au mépris de la puissance de calcul utilisable, il est possible d'utiliser jusqu'à 255 registres 32-bit par thread (contre 63 sur les autres GPU Kepler). C'est principalement important dans le cadre du GPU computing puisqu'en rendu 3D le compilateur va très souvent privilégier un code qui fait appel à moins de registres de manière à maximiser le nombre de vertices ou de pixels qui résident dans le SMX/SMM de manière à mieux masquer les latences élevées, par exemple du texturing.

Enfin, sans changer leur taille, Nvidia a revu le fonctionnement de deux caches importants pour les GPU modernes : le cache de textures (12 Ko) qui dispose d'une voie royale en lecture vers le sous-système mémoire et la mémoire partagée (64 Ko) qui permet d'échanger des données entre threads. La fonction de cache L1 était ainsi combinée à la mémoire partagée sur Kepler alors qu'elle est combinée au texture cache sur Maxwell.

Il faut bien comprendre que dans le cadre d'un GPU Nvidia, le cache L1 ne correspond pas réellement à une espèce de L1D de type CPU qui cacherait les lectures/écritures en mémoire globale. Celles-ci ne sont en cache que via le L2. Le L1 dans le contexte de Kepler est exploité tout d'abord en tant que buffer utilisé lorsque le fichier registre déborde (register spilling). Le compilateur ne peut pas toujours s'assurer que le fichier registre est suffisant et n'a de toute manière pas toujours envie de s'y astreindre pour des raisons de performances. Cette utilisation disparaît cependant avec Maxwell première génération, les registres supplémentaires seront exclusivement en cache via le L2. En d'autres termes, mieux vaut ne pas y avoir recours.

Ensuite, le cache L1 fait office de buffer de regroupement pour les accès mémoire, il y rassemble les données en avance pour qu'elles puissent être délivrées en blocs lors du traitement des warps. Cette utilisation est d'application pour Maxwell comme pour Kepler.

Sur Kepler, la mémoire partagée de 64 Ko accueillait ce L1 avec une répartition qui pouvait être de 16/48, 32/32 ou 48/16, au choix du développeur qui devait le configurer dans le cadre du GPU computing. Sur Maxwell, la mémoire partagée ne remplit que ce seul rôle, ce qui veut dire que la totalité de ses 64 Ko sont disponibles et ce qui simplifie son design. Que ce soit sous CUDA, OpenCL ou DirectCompute, son principe de fonctionnement est le suivant : une partie ou la totalité de la mémoire partagée est attribuée à un bloc de threads et fait office de mémoire pilotée par le programmeur.

La part de mémoire partagée qui peut être réservée par un bloc de threads (de 32 à 1024 threads) reste limitée à 48 Ko pour des raisons de compatibilité. Mais le SMM pourra par exemple accueillir 4 blocs de threads avec 16 Ko chacun, contre 3 blocs pour le SMX. De quoi mieux masquer les latences. A noter que Nvidia avait introduit sur Kepler un accès à pleine vitesse à la mémoire partagée pour les données 64-bit, soit 32x 64-bit par cycle. Jugée peu utile, cette possibilité est passée à la trappe avec Maxwell qui divise donc par deux la bande passante maximale du cette mémoire, ce qui reste suffisant pour débiter 32x 32-bit par cycle.

Si le L1 n'est plus associé à la mémoire partagée, il intègre sur Maxwell les texture caches. Autant sur Kepler que sur Maxwell, chaque bloc de 4 unités de texturing dispose d'un petit cache de 12 Ko qui dispose d'une voie royale vers le sous-système mémoire mais en lecture uniquement. Y intégrer la fonction de L1, d'autant plus limitée au regroupement de données (coalescing) simplifie le design. De 16, 32 ou 48 Ko de L1 Par SMX sur Kepler, Maxwell, tout du moins en première génération, doit se contenter de 2x 12 Ko par SMM. Nvidia estime que cela est suffisant dans le cadre de ces GPU.

A noter qu'avec le GK110, Nvidia a introduit la possibilité, toujours dans le cadre du GPU computing et quand les unités de texturing ne sont pas utilisées, d'exploiter le texture cache en tant que L1D en lecture uniquement. Les accès à la mémoire globale (mémoire vidéo / système) profitent alors d'un "vrai" L1 en plus du L2. Ce mode, qui doit être activé par le développeur s'il le juge utile, est proposé sur Maxwell première génération.

Il ne fait aucun doute selon nous que cette structure des caches sera différente dans le cadre des GPU Maxwell de deuxième génération (GM20x).

Enfin, il faut noter que le niveau de "Compute Capability" fait un bond en avant. Il représente le niveau de fonctionnalité CUDA / OpenCL reporté par le GPU, sur lequel peuvent se baser les développeurs pour des optimisations poussées et sur lequel le compilateur se base pour en sortir le code (au format cubin) adapté à chaque GPU. Le Compute Capability est pour rappel de 3.0 pour les GPU Kepler GK10x et de 3.5 pour le GK110 et le GK208. Il passe à 5.0 pour le GM107 et pour Maxwell de première génération. Un bond en avant difficile à comprendre puisque les différences restent subtiles, tout du moins en apparence. Des différences plus fondamentales dans la manière dans les instructions sont présentées aux GPU existent probablement.

Il faut d'ailleurs préciser qu'un code cubin compilé pour les niveaux 3.0 ou 3.5 ne pourra pas être exécuté sur Maxwell alors qu'un cubin 3.0 reste compatible 3.5, Nvidia ayant fait en sorte de conserver une rétrocompatibilité à l'intérieur d'une même révision majeure. De quoi justifier le passage en 4.0, mais pourquoi en 5.0 ? Mystère, à moins que Nvidia ne se soit inspiré de la culture asiatique dans laquelle le chiffre 4 porte malheur. Certains programmes devront donc être recompilés, raisons pour laquelle Nvidia conseille aux développeurs de toujours inclure une version PTX de leurs kernels, le langage intermédiaire maison de type pseudo-assembleur.
Vos réactions

Top articles