En programmation logicielle, serait-il possible d’avoir une charge de 100% du processeur et du processeur graphique?


43

C’est une question générale sur un sujet que j’ai trouvé intéressant en tant que joueur: les goulots d’étranglement des CPU / GPU et la programmation. Si je ne me trompe pas, j'ai fini par comprendre que le processeur et le processeur graphique calculent des données, mais que l'un est meilleur dans certains calculs que l'autre en raison de la différence d'architecture. Par exemple, le cracking hachage ou l'exploration de crypto-monnaie semble beaucoup plus efficace sur les GPU que sur les CPU.

Je me suis donc demandé: avoir un GPU à 100% de charge alors que le processeur est à 50% (par exemple) est inévitable?

Ou plus précisément: certains calculs normalement effectués par le processeur graphique peuvent-ils être effectués par le processeur si le premier est à 100% de charge, de sorte que les deux atteignent une charge de 100%?

J'ai cherché un peu sur le sujet, mais je suis revenu les mains vides. Je pense et espère que cela a sa place dans cette sous-section et que je suis ouvert à toute documentation ou conférence que vous pourriez me donner!


53
Il est tout à fait possible que le processeur et le processeur graphique exécutent une boucle infinie de NO-OPs en même temps, ce qui entraînera une charge de 100% pour les deux.
Jörg W Mittag

17
Suivant @ Jörg, la seule chose mesurée par le pourcentage de CPU est la fraction de temps qu’on ne passe pas à attendre d’autres processeurs. 100% peut être une bonne chose si le programme est efficace, ou une mauvaise chose si le programme est inefficace. Trop souvent, les utilisateurs se concentrent sur le% de CPU, comme si c’était une mesure de la performance - ce n’est pas le cas.
Mike Dunlavey

22
La Crysis originale a très bien fait ça.
CubicleSoft

5
@ MikeDunlavey vous soulevez un bon point. Avec les voitures, nous ne mesurons pas leurs performances en fonction du nombre de tours par minute, nous mesurons la vitesse.
Captain Man

1
@ JörgWMittag: Le processeur, peut-être. Mais les OS et les GPU ont des problèmes à résoudre pour gérer des boucles infinies. À savoir, si un shader ne termine pas dans un délai raisonnable, il meurt et le GPU est réinitialisé.
Nicol Bolas

Réponses:


62

Théoriquement oui, mais dans la pratique, cela en vaut rarement la peine.

Les processeurs et les GPU sont complets , donc tout algorithme pouvant être calculé par l’un peut également être calculé par l’autre. La question est de savoir à quelle vitesse et quelle commodité.

Bien que le processeur graphique excelle à effectuer les mêmes calculs simples sur de nombreux points de données d'un grand ensemble de données, la CPU est meilleure avec des algorithmes plus complexes comportant de nombreux ramifications. Avec la plupart des problèmes, la différence de performances entre les implémentations de processeur et de processeur graphique est énorme. Cela signifie que l’utilisation de l’un pour prendre le travail de l’autre en décrochage n’entraînerait pas une augmentation notable des performances.

Cependant, le prix à payer pour cela est que vous devez tout programmer deux fois, une fois pour le processeur et une fois pour le GPU. Cela représente plus de deux fois plus de travail, car vous devrez également implémenter la logique de commutation et de synchronisation. Cette logique est extrêmement difficile à tester, car son comportement dépend de la charge actuelle. Attendez-vous à voir très obscur et impossible de reproduire les bugs de cette cascade.


1
Vous avez mentionné qu'avec la plupart des problèmes, la différence de performances entre les implémentations de processeur et de processeur graphique est énorme , mais je suis plutôt intéressé par la mesure dans laquelle l'écart de performance va. Auriez-vous des chiffres ou des articles à ce sujet (par exemple, sur l'exemple du rendu 3D de texture)? Merci pour votre réponse et pour votre temps!
MadWard

2
Vous voudrez peut-être ajouter que la synchronisation entre le processeur et le processeur graphique entraîne des coûts de performance, de sorte que vous souhaitez généralement minimiser le nombre de transferts entre les deux. De plus, ajouter naïvement dans les branches "ne pas exécuter sur les éléments sur lesquels le processeur a déjà travaillé" ne vous rapporterait rien, car les threads du GPU fonctionnent en mode parallèle.
Ethan

3
@gardenhead Rien dans l'univers ne prend en charge la récursion sans limite, car l'univers est de taille finie et a une densité d'informations finie. La «complétude» d'un système est généralement une discussion de ce qui serait possible sans de telles contraintes.
hasard832

3
Je n'ai guère de doute qu'un processeur graphique moderne est techniquement au moins aussi proche de la complétude de Turing qu'un PC des années 80 ... Cependant, si vous essayez d'exécuter des algorithmes généraux sur un processeur graphique, il dégénérera généralement en un processeur séquentiel qui ne le sera pas non plus. plus rapide qu'un PC des années 80, la complétude Turing d'un GPU n'est en pratique guère plus utile que la complétude Turing de Brainfuck .
gauche autour du

7
@leftaroundabout Les GPU modernes sont trivialement complets comme tout processeur . L'exhaustivité turing n'a rien à voir avec: 1) la performance 2) la lisibilité de la source. Les processeurs des années 80 étaient aussi proches de TC que tout le reste: soit ils étaient TC ou ils ne l'étaient pas (cette dernière option étant absurde).
Margaret Bloom

36

Ce n'est pas lié à la programmation de jeux. Certains codes scientifiques peuvent également utiliser à la fois le processeur graphique et le processeur.

Avec une programmation soigneuse et pénible, par exemple en utilisant OpenCL ou CUDA , vous pouvez charger votre processeur graphique et votre processeur à près de 100%. Très probablement, vous aurez besoin d'écrire différents morceaux de code pour le GPU (appelé code "noyau") et pour le CPU, ainsi que du code collant ennuyeux (notamment pour envoyer dans le GPU le code du noyau compilé).

Cependant, le code serait complexe et vous aurez probablement besoin de l'adapter au matériel sur lequel vous travaillez, en particulier parce que la transmission de données entre GPU et CPU est coûteuse.

En savoir plus sur l' informatique hétérogène .

Voir aussi OpenACC , pris en charge par les versions récentes de GCC (par exemple, GCC 6 en juin 2016).


1
Vous avez raison, mes balises et mon titre étaient trompeurs, j'ai supprimé des jeux et ajouté des performances / optimisation. Je ne voulais pas dire que c'était exclusif aux jeux, mais c'est là que je l'ai remarqué. Je pensais que cela devrait aussi être très spécifique au matériel. Merci pour votre réponse et les liens!
MadWard

3
Cela aboutirait à deux algorithmes. Je l'ai essayé une fois: toute l'image à la fois pour le processeur graphique et plusieurs images à la fois pour le processeur (abuser du cache volumineux). C'est en effet douloureux, surtout à maintenir.
PTwr

11

Du point de vue des supercalculateurs, il est préférable de ne pas penser en pourcentage de la charge CPU / GPU mais de déterminer le nombre d'opérations nécessaires à votre problème, puis de le comparer aux performances maximales du système.

Si vous obtenez une utilisation du processeur à 100%, cela ne signifie pas nécessairement que vous obtenez toutes les performances du système. Les processeurs peuvent souvent faire plusieurs choses différentes en même temps, par exemple une division et une addition. Si vous pouvez commencer la division plus tôt, l’ajout risque de chevaucher celle-ci. Le processeur de votre ordinateur de bureau a très probablement une unité en panne qui réorganisera les instructions afin de tirer parti de tels chevauchements. Ou si vous avez le programme suivant:

if (expr1)
    expr2;
else
    expr3;

Un processeur en réorganisation essaiera de calculer les trois expressions en même temps , puis jettera le résultat de l'une d'entre elles. Cela le rend plus rapide en général. Si vous avez un bloqueur dans votre programme et que vous ne pouvez pas réorganiser, vous utilisez moins de voies dans la CPU, mais il affichera probablement encore 100%.

Ensuite, vous avez des fonctions SIMD dans les CPU qui sont des opérations vectorielles. Cela ressemble à GPGPU-light en ce sens que vous n’avez généralement que quatre ou huit opérations à la fois, les GPU en ont 32 ou 64. Vous devez néanmoins l’utiliser pour créer les FLOPS.

Des choses comme un faux partage peuvent engendrer des coûts de synchronisation élevés qui apparaissent généralement sous la forme d'une charge de noyau sous Linux. La CPU est complètement utilisée mais vous n’avez pas beaucoup de débit utile.

J'ai fait de la programmation sur une machine IBM Blue Gene / Q. Il comporte de nombreux niveaux de hiérarchie ( schéma de Blue Gene / L obsolète ) et est donc difficile à programmer efficacement. Vous devrez utiliser la hiérarchie complète allant de SIMD à SMT (Intel appelle cet HyperThreading) pour obtenir des performances optimales.

Et puis le réseau vous limite souvent. Par conséquent, il s'avère que le temps (de l'horloge murale) est plus rapide pour calculer des éléments sur plusieurs processeurs en même temps au lieu de les communiquer via le réseau. Cela mettra plus de charge sur les processeurs et accélérera l'exécution du programme. Toutefois, le débit réel du programme n’est pas aussi bon qu’il semble en ce qui concerne les chiffres bruts.

Si vous ajoutez des GPU au mélange, il deviendra encore plus difficile d'orchestrer tout cela pour générer des performances. Ce sera l’une des choses que je commencerai à faire dans ma thèse de maîtrise sur le QCD du réseau dans quelques mois.


1

Vous voudrez peut-être consulter le moteur de navigation Servo en cours de développement chez Mozilla Research, et plus particulièrement son Web Render (vidéo) .

Bien que déplacer dynamiquement une tâche d'un processeur à un processeur graphique puisse s'avérer peu pratique, comme mentionné dans d'autres réponses (notamment @ Philip's), il peut être pratique d'étudier à l'avance la charge de processeur / GPU sur des charges de travail typiques et de passer de certaines tâches à des tâches généralement moins chargées. une.

Dans le cas de Web Render, la nouveauté est que, traditionnellement, les navigateurs effectuent l'essentiel de leur rendu sur le processeur (le processeur est utilisé pour calculer les objets à afficher, les endroits à couper, etc.). Le GPU est normalement plus performant ... sauf que toutes les utilisations ne sont pas triviales à mettre en oeuvre (suppression partielle, ombres, ... et texte).

Une version initiale de Web Render s’est avérée très efficace pour l’augmentation des performances, mais n’a pas tenté de résoudre le problème du rendu du texte (et comportait quelques autres limitations). Mozilla Research travaille actuellement sur une seconde version qui devrait avoir moins de limitations, et notamment prendre en charge le rendu du texte.

Bien entendu, l’objectif est de décharger le plus possible le processus de rendu sur le GPU, en laissant le processeur libre d’exécuter du Javascript, de mettre à jour le DOM et de toutes les autres tâches.

Ainsi, bien que votre suggestion ne soit pas aussi extrême, elle va dans le sens de la conception d’une stratégie de calcul tenant compte à la fois du processeur et du processeur graphique.


0

En vous concentrant sur les jeux (puisque vous en avez parlé spécifiquement dans votre message), vous pouvez équilibrer la charge de plusieurs manières. Un exemple est le "skinning", c'est-à-dire l'animation d'un modèle. Pour chaque image à restituer, vous devez générer les matrices de transformation pour chaque image d'animation et l'appliquer aux sommets du modèle afin de le transformer en pose à laquelle il doit être placé. Vous devez également interpoler les images pour obtenir un mouvement fluide. , sauf si vous souhaitez que votre animation ressemble au Quake original (c.-à-d. saccadé).

Dans ce cas, vous pouvez le faire sur le processeur et télécharger les résultats sur le GPU pour le rendu, ou effectuer le calcul et le rendu sur le GPU. Je pense qu’à présent, cela se fait sur le GPU (connu sous le nom de "skinning"): cela est logique étant donné que vous avez des calculs relativement simples qui doivent être effectués des milliers de fois, et que chaque sommet peut être calculé simultanément car le résultat du sommet A n'a aucune incidence sur le résultat du sommet B.

Cependant, en théorie, vous pouvez basculer de manière dynamique entre le traitement sur le processeur et le processeur graphique, en fonction de la surcharge du processeur graphique et du processeur.

Le principal obstacle à cette opération dans tous les calculs est toutefois que le processeur et le processeur graphique ont des forces et des faiblesses différentes. Les tâches massivement parallèles sont mieux effectuées sur le processeur graphique, tandis que les tâches linéaires intensives avec ramification sont mieux effectuées sur le processeur. Seuls quelques travaux pourraient être réalisés de manière réaliste sur les deux systèmes sans subir de graves conséquences en termes de performances.

Globalement, le principal problème de la programmation GPU (au moins avec OpenGL et DirectX 11 et inférieur) est que vous avez peu de contrôle sur la façon dont le GPU interprète votre code shader. Il est risqué de créer des branches dans un shader, car si vous créez accidentellement une dépendance entre les calculs, le processeur graphique peut alors décider de commencer à restituer vos pixels un par un, en passant de 60 ips à 10 ips en un instant, même si les données à restituer sont identiques.


0

Un exemple concret est le moteur de rendu Open Source LuxRender , capable de charger entièrement un processeur et un processeur graphique en même temps. En outre, il peut charger plusieurs processeurs graphiques simultanément et peut également être distribué sur plusieurs ordinateurs.

LuxRender utilise OpenCL pour faciliter cela, bien qu'il existe également des versions sans OpenCL.

Ceci est pratique car les algorithmes utilisés par LuxRender sont hautement parallélisables. L'algorithme le plus couramment utilisé par LuxRender est le traçage de chemin , où de nombreux chemins de lumière peuvent être calculés indépendamment les uns des autres, ce qui constitue une situation idéale pour le calcul sur GPU et ne nécessite aucune synchronisation complexe entre les nœuds de calcul. Cependant, les limitations des GPU (faibles quantités de mémoire, manque de prise en charge de certaines fonctionnalités de rendu complexes et manque général de disponibilité pour certains artistes) garantissent que la prise en charge du processeur est toujours essentielle.


quel est le but de montrer cette image, comment est-il pertinent pour la question posée?
moucher

1
Eh bien bien. Je vais le supprimer. Je pensais que cela démontrerait facilement de quel type de logiciel il s'agit. Mais c'est peut-être vraiment distrayant. (Il existe de nombreux types de moteurs de rendu; celui-ci est destiné aux images fixes
réalistes

0

Oui, c'est certainement possible.

Tout calcul qu'un processeur peut faire, un GPU peut aussi le faire, et inversement.

Mais c'est rare parce que:

  • Complexité technique Bien qu'il soit possible d'exécuter le même code sur une CPU et un GPU (par exemple, CUDA), les processeurs ont des capacités et des performances différentes. L'un est MIMD; l'autre, SIMD. Ce qui est rapide sur l'un est lent sur l'autre (par exemple, la création de branches), il est donc nécessaire d'écrire du code séparé pour optimiser les performances.

  • Rentabilité Les GPU sont globalement beaucoup plus puissants que les processeurs. L’idée des GPU est d’utiliser des processeurs moins chers, plus lents, mais plus nombreux pour effectuer des calculs bien plus rapidement que les processeurs ne le pourraient pour le même coût. Les GPU sont plus efficaces en termes de coûts d'un ou deux ordres de grandeur.

Si votre algorithme est exécuté sur des GPU, il est plus logique d’optimiser ces derniers et d’en ajouter autant que vous en avez besoin.

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.