Y a-t-il des avantages à utiliser le processeur au lieu du GPU?


63

J'ai étudié les processeurs et les cartes graphiques et j'ai découvert que les GPU sont bien plus rapides que les processeurs. J'ai lu dans cet article qu'un GPU Nvidia âgé de 2 ans surpassait de 14 fois le processeur Intel Core I7 à 3,2 GHz dans certaines circonstances. Si les GPU sont si rapides, pourquoi les développeurs ne les utilisent-ils pas pour toutes les fonctions d'un jeu? Les GPU peuvent-ils faire autre chose que des graphiques?


17
Si vous êtes dans un jeu dans lequel tout est déchargé sur le processeur graphique et que votre processeur ne fait presque rien, vous pouvez obtenir une augmentation de ses performances en lui redonnant une partie de la charge.
Tetrad

3
votre GPU est peut-être meilleur que votre processeur, mais je ne pense pas que votre carte vidéo soit meilleure que votre carte mère (et je ne comparerai pas le système d'exploitation au pilote lol)
e-MEE

27
GPU is faster than a CPUC'est un faux mythe que beaucoup de gens sont amenés à croire après avoir vu des points de repère basés sur des problèmes spécifiquement conçus pour le GPU (cette catégorie de problèmes est appelée "problèmes parallèles embarrassants"), voir ma réponse à cette question de superutilisateur: Pourquoi utilisons-nous encore Des processeurs au lieu de GPU?
Lie Ryan


5
L'un des avantages est que chaque ordinateur dispose d'un processeur :)
Tim Holt

Réponses:


50

"J'ai lu que les voitures de F1 sont plus rapides que celles que nous conduisons dans la rue ... Pourquoi les gens n'utilisent-ils pas les voitures de F1 alors?" Eh bien ... La réponse à cette question est simple: les voitures de F1 ne peuvent pas casser ou tourner aussi vite que la plupart des voitures (la voiture la plus lente pourrait battre une F1 dans ce cas). Le cas des GPU est très similaire, ils sont bons pour suivre une ligne droite de traitement, mais ils ne sont pas si bons quand il s'agit de choisir des chemins de traitement différents.

Un programme exécuté dans le GPU est logique lorsqu'il doit être exécuté plusieurs fois en parallèle, par exemple lorsque vous devez fusionner tous les pixels de la Texture A avec des pixels de la Texture B et les placer tous dans la Texture C. Cette tâche, lorsqu'elle est exécutée un processeur, serait traité comme suit:

for( int i =0; i< nPixelCount; i++ )
     TexC[i] = TexA[i] + TexB[i];

Mais ceci est lent lorsque vous devez traiter beaucoup de pixels, donc le GPU au lieu d'utiliser le code ci-dessus, il utilise simplement le suivant:

     TexC[i] = TexA[i] + TexB[i];

et puis il remplit tous les cœurs avec ce programme (essentiellement en copiant le programme dans le cœur), en attribuant une valeur ipour chacun. Vient ensuite la magie du GPU et permet à tous les cœurs d’exécuter le programme en même temps , ce qui rend beaucoup d’opérations beaucoup plus rapides que le programme de calcul linéaire.

Cette méthode de travail est acceptable lorsque vous devez traiter de la même manière un grand nombre de petits intrants, mais est vraiment mauvaise lorsque vous devez créer un programme pouvant comporter des branchements conditionnels. Voyons maintenant ce que le processeur fait en matière de vérification des conditions:

  • 1: Exécuter le programme jusqu'à la première opération logique
  • 2: évaluer
  • 3: Poursuivre l'exécution à partir du résultat de l'adresse mémoire de la comparaison (comme avec une instruction JNZ asm)

C'est très rapide pour le processeur de définir un index, mais pour le GPU de faire la même chose, c'est beaucoup plus compliqué. Parce que la puissance du GPU provient de l'exécution simultanée de la même instruction (ce sont des cœurs SIMD), ils doivent être synchronisés pour pouvoir tirer parti de l'architecture de la puce. Devoir préparer le GPU à traiter avec les branches implique plus ou moins:

  • 1: Créez une version du programme qui suit uniquement la branche A, remplissez ce code dans tous les cœurs.
  • 2: Exécuter le programme jusqu'à la première opération logique
  • 3: évaluer tous les éléments
  • 4: Continuez à traiter tous les éléments qui suivent la branche A, mettez en file d'attente tous les processus qui ont choisi le chemin B (pour lequel il n'y a pas de programme dans le noyau!). Désormais, tous les cœurs ayant choisi le chemin B seront au repos - le pire des cas étant celui d’un seul cœur en cours d’exécution, tous les autres étant en attente.
  • 5: Une fois tous les traitements terminés, activez la version branche B du programme (en la copiant à partir des mémoires tampons dans une petite mémoire de base).
  • 6: Exécuter la branche B.
  • 7: Si nécessaire, mélangez / fusionnez les deux résultats.

Cette méthode peut varier en fonction de nombreux facteurs (par exemple, de très petitesles branches sont capables de fonctionner sans avoir besoin de cette distinction), mais vous pouvez maintenant déjà voir pourquoi la création de branches pose problème. Les caches GPU sont très petits, vous ne pouvez pas simplement exécuter un programme à partir de la VRAM de façon linéaire. Il doit copier de petits blocs d’instructions sur les cœurs à exécuter et si vous avez suffisamment de branches, votre GPU sera plus bloqué que l’exécution. n’importe quel code, ce qui n’a aucun sens lorsqu’il s’agit d’exécuter un programme qui ne suit qu’une branche, comme le font la plupart des programmes - même s’il s’exécute dans plusieurs threads. Par rapport à l'exemple F1, cela reviendrait à ouvrir les parachutes de freinage dans tous les coins, puis à sortir de la voiture pour les ranger dans la voiture jusqu'au prochain virage que vous souhaiterez faire demi-tour ou à la recherche d'un sémaphore rouge (le prochain virage). probablement).

Ensuite, il y a bien sûr le problème des autres architectures qui sont si efficaces pour les opérations logiques, beaucoup moins chères et plus fiables, standardisées, mieux connues, à faible consommation d'énergie, etc. Les cartes vidéo les plus récentes sont difficilement compatibles avec les anciennes sans émulation logicielle. utilisez des instructions asm différentes, même celles du même fabricant, et que, pour le moment, la plupart des applications informatiques ne requièrent pas ce type d'architecture parallèle, et même si elles en ont besoin, elles peuvent utiliser des API standard telles que OpenCL mentionné par eBusiness, ou à travers les apis graphiques. Dans quelques décennies probablement, nous aurons des GPU pouvant remplacer les processeurs, mais je ne pense pas que cela se produira de si tôt.

Je recommande la documentation de l'application AMD qui explique beaucoup de choses sur l'architecture de leurs GPU. J'ai également vu les NVIDIA dans les manuels CUDA, ce qui m'a beaucoup aidé à comprendre cela. Je ne comprends toujours pas certaines choses et je me trompe peut-être. Une personne qui en sait plus peut confirmer ou infirmer mes déclarations, ce qui serait très bien pour nous tous.


6
analogie étrange mais c'est un bon point que the fastest isn't always the fastest.
Lie Ryan

1
Merci! Je pense que c'est un sujet intéressant car il lie de nombreux concepts de programmation de jeux à la façon dont fonctionne le matériel, ce qui est quelque peu oublié dans le pays des langages de haut niveau actuels. Il y a quelques autres choses que j'aimerais ajouter, mais écrire la réponse prenait déjà un peu de temps, alors je vais essayer de la mettre à jour plus tard, comme les capacités "en mode protégé" des CPU, la vitesse du bus mémoire, etc., mais j'espère que cela clarifiera quelques inconvénients techniques de tout exécuter dans le gpu.
Pablo Ariel

6
L'analogie serait bien meilleure si elle était exacte. Les voitures de F1 ont d’énormes capacités de freinage qui leur permettent de maintenir une vitesse élevée dans une courbe au lieu de commencer à freiner longtemps à l’avance. Les virages à haute vitesse sont également meilleurs grâce aux fortes descentes, bien que le rayon de braquage ne soit probablement pas excellent pour les parkings. Les meilleures raisons pourraient inclure le manque d'espace de stockage, de rétroviseur, de climatisation, de régulateur de vitesse, de protection contre les éléments, de sièges passagers, de suspension et de dégagement pour les routes en mauvais état, ou de diverses autres choses courantes dans les véhicules de tourisme.
GargantuChet

5
@Pablo Ariel Je réponds à la déclaration: "Les voitures de F1 ne peuvent pas casser ou tourner aussi vite que la plupart des voitures". Vous suggérez que les voitures de F1 ne peuvent accélérer qu'en ligne droite et qu'elles ne sont pas très bonnes en virage ou en décélération. Mais les voitures de F1 freinent beaucoup plus vite que la plupart des voitures et sont excellentes dans les virages à haute vitesse.
GargantuChet

4
L'analogie est plus précise si vous pensez aux Dragsters plutôt qu'aux voitures de F1
Agustin Meriles

32

Les GPU sont une très bonne tâche parallèle. Ce qui est génial ... si vous exécutez des tâches parallèles.

Les jeux représentent le type d'application le moins parallélisable. Pensez à la boucle de jeu principale. L'IA (supposons que le joueur soit traité comme un cas particulier de l'IA) doit réagir aux collisions détectées par la physique. Par conséquent, il doit être exécuté par la suite. Ou à tout le moins, la physique doit appeler des routines d'IA dans les limites du système physique (ce qui n'est généralement pas une bonne idée pour de nombreuses raisons). Les graphiques ne peuvent pas s'exécuter tant que la physique n'a pas fonctionné, car c'est la physique qui met à jour la position des objets. Bien entendu, l'IA doit être exécutée avant le rendu, car l'IA peut générer de nouveaux objets. Les sons doivent courir après l'IA et les commandes du joueur

En général, les jeux peuvent se faufiler de très peu de façons. Les graphiques peuvent être créés dans un fil de discussion; la boucle de jeu peut envoyer un tas de données sur le fil graphique et dire: restituer ceci. Il peut effectuer une interpolation de base, de sorte que la boucle de jeu principale ne soit pas nécessairement synchronisée avec les graphiques. Le son est un autre fil conducteur. la boucle du jeu dit "joue ceci", et c'est joué.

Après cela, tout commence à devenir douloureux. Si vous avez des algorithmes de cheminement complexes (comme pour les RTS), vous pouvez les threader. Quelques algorithmes peuvent être nécessaires pour que les algorithmes soient terminés, mais ils seront au moins concurrents. Au-delà, c'est assez difficile.

Vous avez donc 4 thèmes: le jeu, les graphiques, le son et éventuellement le traitement à long terme de l'IA. Ce n'est pas beaucoup. Et ce n'est pas presque assez pour processeurs graphiques, qui peuvent avoir des centaines de fils en vol à la fois. C'est ce qui donne aux GPU leurs performances: être capable d'utiliser tous ces threads en même temps. Et les jeux ne peuvent tout simplement pas faire ça.

Maintenant, vous pourrez peut-être aller "à fond" pour certaines opérations. Les IA, par exemple, sont généralement indépendants les uns des autres. Ainsi, vous pouvez traiter plusieurs dizaines d'IA à la fois. Jusqu'à ce que vous deviez réellement les rendre dépendants les uns des autres. Alors vous êtes en difficulté. Les objets de la physique sont également indépendants ... sauf s’il existe une contrainte entre eux et / ou qu’ils entrent en collision avec quelque chose. Ensuite, ils deviennent très dépendants.

De plus, il y a le fait que le processeur graphique n'a tout simplement pas accès aux entrées de l'utilisateur, ce qui, si j'ai bien compris, est assez important pour les jeux. Donc, cela devrait être fourni. Il n’a pas non plus accès direct aux fichiers ni aucune méthode réelle de communication avec le système d’exploitation; Encore une fois, il devrait y avoir un moyen de fournir cela. Oh, et tout ce traitement du son? Les GPU n'émettent pas de sons. Donc, ceux-ci doivent retourner à la CPU et ensuite à la puce son.

Oh, et coder pour les GPU est terrible. Il est difficile de faire le bon choix, et ce qui est «juste» pour une architecture de processeur graphique peut être très, très mauvais pour une autre. Et ce n'est même pas simplement passer d'AMD à NVIDIA; cela pourrait être de passer d'une GeForce 250 à une GeForce 450. C'est un changement d'architecture de base. Et cela pourrait facilement rendre votre code mal exécuté. C ++ et même C ne sont pas autorisés; le meilleur que vous obtenez est OpenCL, qui est un peu comme C mais sans quelques subtilités. Comme récursion . C'est vrai: pas de récursion sur les GPU.

Débogage? Oh, j'espère que vous n'aimez pas les fonctionnalités de débogage de votre IDE, car celles-ci ne seront certainement pas disponibles. Même si vous utilisez GDB, embrasse-le. Vous devrez recourir au printfdébogage ... attendez, il n'y a pas printfde GPU. Vous devrez donc écrire dans des emplacements de mémoire et faire en sorte que votre programme de stub de processeur les relise.

C'est vrai: débogage manuel . Bonne chance avec ça.

En outre, ces bibliothèques utiles que vous utilisez en C / C ++? Ou peut-être que vous êtes plus du genre .NET, utilisant XNA, etc. Ou peu importe. Peu importe, vous ne pouvez en utiliser aucun sur le GPU. Vous devez tout coder à partir de zéro. Et si vous avez une base de code existante, difficile: il est temps de réécrire tout ce code.

Donc voilà. C'est horrible à faire pour tout type de jeu complexe. Et ça ne marcherait même pas, parce que les jeux ne sont tout simplement pas assez parallèles pour que ça aide.


21

Pourquoi n'est-il pas si facile de répondre - il est important de noter que les GPU sont des processeurs spécialisés qui ne sont pas vraiment destinés à une utilisation généralisée, contrairement à un processeur ordinaire. En raison de cette spécialisation, il n’est pas surprenant qu’un processeur graphique puisse surpasser les capacités d’un processeur pour les objets pour lesquels il avait été spécifiquement conçu (et optimisé), mais cela ne signifie pas nécessairement qu’il peut remplacer toutes les fonctionnalités et les performances d’un processeur généralisé.

Je soupçonne que les développeurs ne le font pas pour diverses raisons, notamment:

  • Ils veulent que les graphiques soient aussi rapides et de la meilleure qualité possible, et l’utilisation de ressources GPU précieuses pourrait gêner cela.

  • Du code spécifique au GPU devra peut-être être écrit, ce qui introduira probablement une complexité supplémentaire dans la programmation globale du jeu (ou de l'application) concerné.

  • Un GPU n’a normalement pas accès aux ressources telles que les cartes réseau, les claviers, les souris et les manettes de jeu. Il n’est donc pas possible pour lui de gérer tous les aspects du jeu.

En réponse à la deuxième partie de votre question: Oui, il y a d'autres utilisations. Par exemple, des projets tels que SETI @ Home (et probablement d’autres projets BOINC) utilisent des GPU (tels que ceux de nVidia) pour les calculs complexes à grande vitesse:

  Exécutez SETI @ home sur votre GPU NVIDIA
  http://setiathome.berkeley.edu/cuda.php

( J'aime votre question car elle pose une idée intéressante. )


18

Les processeurs sont plus flexibles, il est généralement plus facile de les programmer, ils peuvent exécuter des threads uniques beaucoup plus rapidement.

Bien que les GPU modernes puissent être programmés pour résoudre pratiquement toutes les tâches, ils ne gagnent en vitesse qu'en utilisant leur architecture parallèle. C'est généralement le cas de tâches "simples" hautement répétitives. Une grande partie du code que nous écrivons crée des branches trop imprévisibles pour fonctionner efficacement sur un processeur graphique.

En plus de tout cela, vous pourriez perdre beaucoup de temps à optimiser le code de différentes puces graphiques. Bien qu'OpenCL soit disponible pour faire en sorte que le même code réponde à un grand nombre de puces graphiques différentes, vous allez échanger un avantage de vitesse pour ce luxe.

Du point de vue des programmeurs de jeux, nous souhaitons généralement que notre jeu fonctionne sur des ordinateurs dotés de cartes graphiques de moindre qualité. Certaines des puces intégrées ne disposent pas de la programmabilité requise, mais si elles le sont, elles sont tellement lentes qu'elles ne battront pas le processeur avec une très grande marge, même pour le type de travail pour lequel elles devraient être performantes. Et bien sûr, si vous exploitiez un GPU bas de gamme pour un jeu, vous auriez besoin de la puissance de traitement du rendu graphique.

En effet, les perspectives sont excellentes, mais lorsque vous créez un jeu plutôt que de déchiffrer des mots de passe, les problèmes pratiques l'emportent dans la plupart des cas sur les avantages.


6

Les GPU sont très difficiles à programmer. Vous devriez chercher comment trier une liste sur un GPU . Beaucoup de thèses ont cherché à le faire.

Utiliser un processeur avec un seul thread est facile, utiliser multi-thread est plus difficile, utiliser de nombreux ordinateurs avec une bibliothèque parallèle car PVM ou MPI est difficile et utiliser un gpu est le plus difficile.


4

Outre ce que Randolf Richardson a répondu, il existe certaines fonctionnalités que les processeurs GPU ne peuvent gérer par eux-mêmes. Par exemple, certaines des commandes de gestion de la mémoire graphique sont traitées par la CPU car le GPU ne peut pas les gérer.

Et il y a une autre grande raison, le GPU est conçu pour les calculs multithread. Cela signifie que les fabricants de GPU peuvent facilement ajouter des cœurs chaque fois qu'ils souhaitent augmenter la puissance de calcul. Mais il existe de nombreuses tâches qui ne peuvent pas être divisées en problèmes plus petits, tels que le calcul du nième nombre de la série de Fibonacci . Dans ces situations, le processeur est beaucoup plus rapide car il est plus optimisé pour les tâches à un seul thread.


4

De nombreuses réponses suggèrent que les GPU ne sont que plus rapides car ils gèrent les tâches en parallèle. Cela exagère un peu la question. Les GPU peuvent être plus efficaces pour d'autres raisons, telles que pouvoir avoir un accès mémoire plus restrictif, ne pas avoir à supporter autant de types de données, pouvoir avoir un jeu d'instructions plus efficace, etc. Les premiers GPU ne pouvaient toujours dessiner qu'un pixel à une fois, mais c’était le fait qu’ils pouvaient faire un cycle à chaque cycle qui importait.

La vraie différence réside dans le fait qu’il s’agit de deux types de machines différentes qui sont personnalisées pour s’exécuter correctement dans différentes catégories de tâches qui semblent similaires mais qui sont en réalité très différentes. C'est comme comparer un avion à une voiture. La vitesse maximale de l'avion est beaucoup plus grande, mais son utilisation est soumise à davantage de restrictions. Dans les cas où vous pouvez faire le même voyage avec l'un ou l'autre type, l'avion semble supérieur.


L’analogie avec l’avion est très bonne (+1), mais s’agissant des processeurs prenant en charge différents types de données, il s’agit plutôt d’un concept de langage de niveau supérieur, car les processeurs (du moins dans l’espace Intel) ont tendance à traiter données sous des formes très basiques (par exemple, bits, octets, mots, dwords, etc.). Il existe des instructions en boucle étroite pour numériser ou copier des données qui se terminent par un octet nul, mais les données dans ces instances ne sont pas réellement reconnues par le processeur comme étant d'un type particulier (à l'exception d'un bloc de données à terminaison zéro dans le contexte de ces boucles).
Randolf Richardson

@ Randolf: les processeurs ont des instructions et des registres différents qui traitent différents types de données de bas niveau (par exemple, signé par rapport à non signé, intégral par rapport à une virgule flottante). C'est le cas de 8086 et de la plupart des architectures modernes, et cela ne vient pas entièrement gratuitement.
Kylotan

Je suis sûr qu'ils font encore beaucoup de traitement linéaire dans l'architecture sous-jacente. Du côté de la programmation, il suffit d’une instruction au GPU, mais les cœurs ne s’exécutent pas exactement en parallèle car ils dépendent d’un autre matériel qui n’est pas parallèle, comme la lecture de la mémoire. Le GPU peut probablement fournir des données à un seul un temps.
Pablo Ariel

3

Les développeurs n'utilisent les GPU pour toutes les fonctions qu'ils sont bons. Ils utilisent des processeurs pour toutes les fonctions pour lesquelles ils sont bons. Qu'est-ce qui vous fait penser qu'ils ne le font pas?

Les GPU conviennent bien aux tâches qui peuvent être massivement paralellisées et nécessitent des calculs volumineux nécessitant peu de mémoire, ou une corrélation temporelle élevée ne nécessitant que de petites prises de décision. Cela inclut le rendu des images, des simulations physiques (particules, collision, tissu, eau, réflexion), etc. C'est précisément pour cela que les jeux modernes utilisent le GPU.

Les processeurs sont efficaces pour les tâches qui ne sont pas bien parallélisées et qui nécessitent une énorme quantité de décisions. Ils peuvent tolérer des exigences de mémoire élevées même avec une corrélation temporelle modérée. Cela inclut l'intelligence artificielle, l'interface utilisateur, les E / S disque et réseau, etc. C'est précisément pour cela que les jeux modernes utilisent le processeur.


1

La relecture est une autre raison pour laquelle je peux penser à préférer de temps en temps le processeur. Pas en termes de bande passante (car la bande passante GPU-> CPU n'est pas tellement un problème sur le matériel moderne) mais en termes de blocage du pipeline. Si vous avez besoin d'extraire des résultats d'un calcul et de faire quelque chose d'intéressant ou d'utile, utiliser le GPU n'est pas un choix judicieux (dans le cas général (il y aura des cas particuliers où il peut rester approprié)), car la relecture nécessitera toujours le GPU pour arrêter ce qu’il fait, effacer toutes les commandes en attente et attendre la fin de la relecture. Cela peut nuire aux performances dans la mesure où non seulement il supprime les avantages de l’utilisation du processeur graphique, mais peut également être considérablement plus lent.


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.