web-dev-qa-db-fra.com

Dans la programmation logicielle, serait-il possible d'avoir des charges CPU et GPU à 100%?

C'est une question générale sur un sujet que j'ai trouvé intéressant en tant que joueur: les goulots d'étranglement CPU/GPU et la programmation. Si je ne me trompe pas, j'ai compris que le CPU et le GPU calculent des choses, mais que l'un est meilleur dans certains calculs que l'autre en raison de la différence d'architecture. Par exemple, le craquage de hachages ou l'extraction 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 CPU est à 50% (par exemple) inévitable?

Ou, plus précisément: Certains calculs qui sont normalement effectués par le GPU peuvent-ils être effectués par le CPU 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 j'espère que cela a sa place dans cette sous-section et je suis ouvert à toute documentation ou conférence que vous pourriez me donner!

43
MadWard

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

Les CPU et les GPU sont tous deux turing-complete , donc tout algorithme qui peut être calculé par l'un peut également être calculé par l'autre. La question est de savoir à quelle vitesse et à quel point cela est pratique.

Alors que le GPU excelle à faire les mêmes calculs simples sur de nombreux points de données d'un grand ensemble de données, le CPU est meilleur dans les algorithmes plus complexes avec beaucoup de branchements. Avec la plupart des problèmes, la différence de performances entre les implémentations CPU et GPU est énorme. Cela signifie que l'utilisation de l'un pour prendre le travail de l'autre lorsqu'il est au point mort n'entraînerait pas vraiment une augmentation notable des performances.

Cependant, le prix à payer est que vous devez tout programmer deux fois, une fois pour le CPU et une fois pour le GPU. C'est 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 à très obscur et impossible à reproduire les bugs de cette cascade.

62
Philipp

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

Avec une programmation minutieuse et douloureuse, par ex. en utilisant OpenCL ou CUDA , vous pouvez charger à la fois votre GPU et votre CPU à 100%. Vous aurez très probablement besoin d'écrire différents morceaux de code pour le GPU (ce qu'on appelle le code "noyau") et pour le CPU, et du code de colle ennuyeux (notamment pour envoyer dans le GPU le code noyau compilé).

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

En savoir plus sur calcul hétérogène .

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

36

Du point de vue du supercalcul, il est préférable de ne pas penser en pourcentage de charge CPU/GPU, mais plutôt de déterminer le nombre d'opérations dont votre problème a besoin, puis de le comparer aux performances maximales du système.

Si vous obtenez 100% d'utilisation du processeur, 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 un ajout. Si vous pouvez commencer la division tôt, elle peut éventuellement se chevaucher avec l'ajout. Votre CPU de bureau a très probablement une unité hors service qui réorganisera les instructions afin de bénéficier de ces chevauchements. Ou si vous avez le programme suivant:

if (expr1)
    expr2;
else
    expr3;

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

Ensuite, vous avez des fonctionnalités SIMD dans les CPU qui sont des opérations vectorielles. C'est comme GPGPU-light dans le sens où vous n'avez généralement que quatre ou huit opérations en même temps, les GPU en font 32 ou 64. Vous devez toujours l'utiliser pour démarrer les FLOPS.

Des trucs comme un faux partage peuvent entraîner un coût de synchronisation élevé qui apparaît généralement comme une charge du noyau sous Linux. Le CPU est complètement utilisé mais vous n'avez pas beaucoup de débit utile.

J'ai fait de la programmation sur une machine IBM Blue Gene/Q. Il a 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 jusqu'à SIMD et SMT (Intel appelle cela HyperThreading) afin d'obtenir les performances.

Et puis le réseau vous limite souvent. Par conséquent, il s'avère qu'il est plus rapide (horloge murale) de calculer les choses sur plusieurs processeurs en même temps au lieu de les communiquer sur le réseau. Cela mettra plus de charge sur les CPU et rendra le programme plus rapide. Mais le débit réel du programme n'est pas aussi bon qu'il semble d'après les chiffres bruts.

Si vous ajoutez des GPU au mixage, il sera encore plus difficile d'orchestrer tout cela pour obtenir des performances. Ce sera l'une des choses que je vais commencer à faire dans ma thèse de master Lattice QCD dans quelques mois.

11
Martin Ueding

Vous pourriez être intéressé par la vérification du moteur de navigateur Servo en cours de développement chez Mozilla Research, et plus précisément son Rendu Web (vidéo) .

Bien que le déplacement dynamique d'une tâche du CPU vers le GPU puisse être impossible, comme mentionné dans d'autres réponses (notamment @ Philip's), il peut être pratique d'étudier à l'avance la charge de CPU/GPU sur des charges de travail typiques et de basculer certaines tâches à celles généralement moins chargées.

Dans le cas de Web Render, la nouveauté est que les navigateurs effectuent traditionnellement la plupart de leur travail de rendu sur le CPU (c'est-à-dire que le CPU est utilisé pour calculer les objets à afficher, où couper, etc ...). Le GPU est normalement meilleur dans ce domaine ... sauf que toutes les utilisations ne sont pas triviales à mettre en œuvre (élimination partielle, ombres, ... et texte).

Une version initiale de Web Render s'est avérée très efficace dans l'augmentation des performances, mais n'a pas essayé de résoudre le problème du rendu de texte (et avait quelques autres limitations). Mozilla Research travaille actuellement sur une deuxième version qui est censée avoir moins de limitations, et notamment pour supporter le rendu de texte.

Le but, bien sûr, est de décharger autant que possible le processus de rendu sur le GPU, laissant le CPU libre d'exécuter Javascript, de mettre à jour le DOM et toutes les autres tâches.

Donc, bien que pas aussi extrême que votre suggestion, cela va dans le sens de la conception d'une stratégie de calcul avec à la fois CPU et GPU à l'esprit.

1
Matthieu M.

En mettant l'accent sur les jeux (puisque vous l'avez mentionné spécifiquement dans votre message), il existe plusieurs façons d'équilibrer la charge. Un exemple est le "skinning", c'est-à-dire l'animation d'un modèle. Pour chaque image à rendre, vous devez générer les matrices de transformation pour chaque image d'animation et les appliquer aux sommets du modèle pour le transformer en la pose dans laquelle il doit être. Vous devez également interpoler les images pour obtenir un mouvement fluide , à moins que vous ne souhaitiez que votre animation ressemble au tremblement de terre d'origine (c'est-à-dire saccadé).

Dans cette situation, vous pouvez le faire sur le processeur et télécharger les résultats sur le GPU pour le rendu, ou faire le calcul et le rendu sur le GPU. Je pense que cela se fait de nos jours sur le GPU (connu sous le nom de "skin skinning"): cela a du sens de le faire étant donné que vous avez des calculs relativement simples qui doivent être effectués des milliers de fois, et chaque sommet peut être calculé simultanément depuis le résultat du sommet A n'a aucune incidence sur le résultat du sommet B.

En théorie cependant, vous pouvez basculer dynamiquement entre le faire sur le CPU ou le GPU en fonction de la surcharge du GPU et du CPU.

Cependant, le principal obstacle à cette opération dans tous les calculs est que le CPU et le GPU ont des forces et des faiblesses différentes. Les tâches massivement parallèles sont mieux effectuées sur le GPU, tandis que les tâches linéaires intensives avec branchement sont mieux effectuées sur le CPU. Seuls quelques travaux pourraient être réalisés de manière réaliste sur les deux sans un sérieux coup de performance.

Dans l'ensemble, le problème majeur avec la programmation GPU (au moins avec OpenGL et DirectX 11 et versions antérieures) est que vous avez peu de contrôle sur la façon dont le GPU interprète votre code de shader. La création de branches dans un shader est risquée car si vous créez accidentellement une dépendance entre les calculs, le GPU peut décider de commencer à rendre vos pixels un par un, en transformant 60 images par seconde en 10 images par seconde en dépit des données réelles à rendre identiques.

0
Richard Greenlees

Un exemple réel est le moteur de rendu open source LuxRender , qui est capable de charger complètement un CPU et un GPU en même temps. En outre, il peut charger plusieurs GPU en même temps et peut également être réparti sur plusieurs ordinateurs.

LuxRender utilise OpenCL pour faciliter cela, bien que des builds sans OpenCL existent également.

Ceci est pratique car les algorithmes utilisés par LuxRender sont hautement parallélisables. L'algorithme le plus couramment utilisé par LuxRender est traçage de chemin , où de nombreux chemins de lumière individuels peuvent être calculés indépendamment les uns des autres - une situation idéale pour le calcul GPU et qui ne nécessite aucune synchronisation complexe entre les nœuds de calcul. Cependant, les limitations des GPU (moins 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.

0
PythonNut

Oui, c'est certainement possible.

Tout calcul qu'un CPU peut faire, un GPU peut aussi le faire, et vice versa.

Mais c'est rare car:

  • complexité de l'ingénierie Bien qu'il soit possible d'exécuter le même code sur un CPU et un GPU (par exemple CUDA), les processeurs ont des capacités et des caractéristiques de 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 ramification), vous avez donc besoin d'écrire du code séparé pour maximiser les performances.

  • Rentabilité Les GPU sont globalement beaucoup plus puissants que les CPU. L'idée générale des GPU est d'utiliser des processeurs moins chers, plus lents, mais plus nombreux pour effectuer des calculs beaucoup plus rapidement que les CPU 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 vous faites fonctionner votre algorithme sur des GPU, il est plus logique de les optimiser et d'en ajouter autant que vous le souhaitez.

0
Paul Draper