Multi-plateforme multi-threading: Quels sont les vrais défis?

21

Alors qu'une bibliothèque comme SDL fournit une API wrapper multiplateforme pour le filetage, je pense qu'il serait naïf de supposer que cela conduit directement au développement facile de jeux sur des plates-formes très différentes (ordinateur de bureau / mobile).

Quelle est la meilleure façon d'aborder le développement de cette manière (compte tenu de toute API de threading multiplateforme) compte tenu des éléments suivants:

  • différents nombres de noyaux
  • capacités de traitement très différentes par cœur
  • Une architecture de systèmes généralement différente avec par exemple. différentes latences pour le cache, la RAM et l'accès aux E / S

J'ai l'impression que la seule façon de le faire est d'évaluer le nombre de threads pouvant être exécutés pour chaque appareil que vous avez l'intention de prendre en charge et de déterminer le plus petit dénominateur commun. Cependant, cela me laisse encore dans le noir quant à la quantité totale de débit de traitement disponible. Ai-je raison de supposer que la seule façon de le faire efficacement est de développer activement l'appareil mobile le moins cher que j'ai l'intention de prendre en charge, tout au long du développement? - c'est-à-dire le plus petit dénominateur commun? Cela devrait-il être à peu près suffisant? Ou y a-t-il plus que cela?

EDIT: S'il vous plaît, d'autres pourraient-ils offrir une expérience supplémentaire à ce sujet, car je ne pense pas que ma question ait reçu une réponse complète pour le moment.

Ingénieur
la source
Comme ma réponse ne répond pas entièrement à votre question, pourriez-vous détailler ce qui manque / ce que vous voulez savoir? Je ne suis peut-être pas un grand écrivain mais j'ai traité ce genre de problème plus d'une fois.
Valmond
Vous n'avez vraiment pas répondu à la question, qui portait sur les difficultés de multithreading et comment les surmonter lors du développement pour des plates-formes avec différentes capacités de threading . Voir mon paragraphe sous les puces. Vous parlez de tailles d'écran et de résolutions - cela n'a rien à voir avec ma question - lisez le titre.
Ingénieur
1
Je suppose que la difficulté vient de ce que vous voulez utiliser les threads. C'est une chose d'avoir un thread d'assistance faisant quelque chose sur le côté, et complètement autre pour essayer de presser les derniers bits de performance d'une machine à 8 cœurs. De mon point de vue, les threads SDL sont principalement destinés au premier, pas ce dernier.
Jari Komppa

Réponses:

11

Vous parlez de "difficultés multithreads" mais de quelles difficultés parlez-vous réellement? D'une certaine manière, vous citez un problème fantôme qui n'existe peut-être même pas. Le vrai défi est celui que vous vous lancez - si vous êtes absolument déterminé à tirer le maximum de puissance d'un morceau de matériel, cela implique d'utiliser le matériel au mieux, mais cela élargit également l'écart entre la machine la plus puissante et les moins puissants. L'implication de ceci est que si vous avez un jeu qui tire vraiment le meilleur parti d'une PS3 (par exemple), vous ne pouvez pas vraiment l'exécuter sur un téléphone portable bon marché de toute façon, donc votre problème n'est plus "comment puis-je obtenir 1 programme pour travailler sur du matériel très différent "mais devient" comment puis-je implémenter 1 idée de jeu de différentes manières pour qu'elle fonctionne sur du matériel de puissance différente ".

Alors qu'une bibliothèque comme SDL fournit une API wrapper multiplateforme pour le filetage, je pense qu'il serait naïf de supposer que cela conduit directement au développement facile de jeux sur des plates-formes très différentes (ordinateur de bureau / mobile).

Développement facile de jeux - bien sûr. Multithreading optimal, non. Mais vous n'avez pas besoin de multithreading pour créer des jeux. Pour en faire de hautes performances, cela aide certainement. Mais de nombreux grands jeux fonctionnent sur un seul thread.

Quelle est la meilleure façon d'aborder le développement de cette manière (compte tenu de toute API de threading multiplateforme) compte tenu des éléments suivants:

  • différents nombres de noyaux
  • capacités de traitement très différentes par cœur
  • Une architecture de systèmes généralement différente avec par exemple. différentes latences pour le cache, la RAM et l'accès aux E / S

Au lieu d'essayer d'affecter des systèmes à des threads, affectez des tâches aux threads. Donnez à chaque tâche les données dont elle a besoin pour exécuter et regrouper les tâches selon le matériel disponible. Habituellement, vous aurez une sorte de pool de threads pour abstraire les différents cœurs ou processeurs, et un gestionnaire de tâches qui a une file d'attente de tâches et les renvoie aux différents threads lorsque le thread signale qu'il a terminé la tâche précédente et est prêt pour un nouveau. Le matériel avec plus de cœurs accomplira évidemment les tâches plus rapidement et pourra rendre plus rapidement. La spécialisation de ce système pour travailler de manière optimale sur des systèmes ayant des caractéristiques différentes devient un problème d'optimisation avancé, mais peut être basée sur certaines heuristiques (par exemple, une tâche qui ne fonctionne pas).

Cependant, la décomposition des fonctionnalités du jeu en tâches discrètes est une question assez complexe et ne vaut souvent pas la peine à moins que vous ne soyez très sûr d'avoir besoin des performances, donc la plupart ne tenteront même pas.

Quelques lectures supplémentaires:

http://www.gamasutra.com/view/feature/1830/multithreaded_game_engine_.php - voir la section «données parallèles». Avec ce modèle, les données sont réparties sur plusieurs tâches identiques et regroupées sur des threads individuels.

http://software.intel.com/en-us/articles/designing-the-framework-of-a-parallel-game-engine/ - assez dense, décrit les choses au niveau du système d'exploitation plutôt qu'au niveau du jeu.

http://drdobbs.com/high-performance-computing/216500409 - pas spécifique au jeu, mais tout à fait pertinent pour vous dire comment vous devez répartir les tâches.

http://www.itfgaming.com/news/tech-focus-crysis-2-and-the-future-of-cryengine-3 - à mi-chemin de cette interview est une anecdote sur la façon dont ils ont migré vers un système basé sur les tâches .

Kylotan
la source
Très bons points. Et c'est vrai, j'ai utilisé le mot «difficultés» quand «défis» serait plus précis. Vous avez dit: "La décomposition des fonctionnalités du jeu en tâches discrètes est une question assez complexe et ne vaut souvent pas la peine sauf si vous êtes très sûr d'avoir besoin des performances, donc la plupart ne le tenteront même pas." Pouvez-vous élaborer sur ce sujet? Fournir des sources? C'est un peu vague, mais je dirais que vous allez au cœur du problème.
Ingénieur
Désolé, je pensais que ce type d'approche était bien connu. Je vais développer la réponse.
Kylotan
4

Quand j'ai fait des jeux mobiles, nous avons d'abord développé une version «or» (c'est-à-dire un jeu entièrement fonctionnel), puis nous l'avons divisé en 3 versions principales (grand écran, taille moyenne et petit écran). Celles-ci ont été converties en 11 versions: graphiques exigeants (la lecture prend beaucoup de mémoire / processeur) vs profil bas, etc. (il y avait aussi quelques versions de plate-forme spéciales).

Le plus gros problème était (c'était mon travail entre autres) d'isoler les plates-formes nécessaires et de déterminer ces versions et comment les créer (c.-à-d. Grand écran mais profil bas devrait être une version déclassée du grand écran / profil hi ou devrait-il être écran de taille moyenne / profil lo fait grand écran?).

Bien sûr, nous avons codé dans cet esprit, donc les jeux étaient très peu attachés à la taille de l'écran.

HTH

[modifier] Ce que je voulais dire, c'est que vous devez diviser vos plates-formes cibles en différentes qualités (c'est-à-dire 1 cœur, 2 cœurs, 1 cœur mais deux fois plus vite ...) Ensuite, décidez du nombre de cibles virtuelles que vous souhaitez (par exemple " un seul "ou" Faible, Moyen, Salut ") Ensuite, placez toutes les plates-formes dans leur" qualité "respective et pour chaque qualité, prenez le dénominateur le plus bas et" portez "le code afin qu'il soit conforme à ces exigences (c'est-à-dire qu'il fonctionne et est rapide suffisant).

Il peut sembler que vous devez le faire avec beaucoup de conjectures, mais vous pouvez déjà trouver la pire qualité avec la pire plate-forme. Je choisirais chaque qualité suivante au moins "deux fois plus bonne" que la première, cela ne générerait probablement pas plus que 3-4 "qualités". Si le code est porté à partir d'une version or, toute plate-forme qui ne fonctionne pas assez bien pourrait simplement être rétrogradée à une `` qualité '' inférieure pour l'accélérer. Toute nouvelle plate-forme pourrait également être placée assez facilement dans la bonne qualité.

Valmond
la source
Sur le haut de votre tête, combien de temps supplémentaire diriez-vous que le projet avait à la fois dans les phases de conception et de développement, pour accueillir une version multi-plateforme comme celle-ci? Juste une moyenne approximative aiderait.
Ingénieur
1
Eh bien, comme nous l'avons fait en plusieurs langues (anglais, français, espagnol, portugais, allemand et italien dans un pack + quelle que soit la langue requise par la journée, taïwanais, turc, russe ...) et nous avions de nouvelles plates-formes que nous devions "porter" tous nos jeux à tous les quelques mois (lire une nouvelle classe de mobiles) nous aurions en fait perdu beaucoup de temps sans aller de cette façon, cela aurait vraiment été impossible sans un très gros tem. La conception du «cadre» a été faite sur le pouce alors que j'en apprenais sur différents mobiles et que je suis arrivé à maturité après peut-être 3-4 ans. Un investissement qui en vaut la peine.
Valmond
1

J'ai l'impression que la seule façon de procéder consiste à évaluer le nombre de threads pouvant être exécutés pour chaque périphérique que vous avez l'intention de prendre en charge et à déterminer le plus petit dénominateur commun.

Pas nécessairement - il peut y avoir de l'espoir pour une solution plus dynamique, mais cela dépend du problème réel que vous essayez de résoudre (le cas échéant). Vous êtes un peu vague dans votre question, donc ma réponse doit aussi être vague.

Si le regroupement de plates-formes sur lequel vous prévoyez de fonctionner a la capacité d'énumération matérielle via une API, vous pouvez utiliser cette interface pour détecter le nombre maximal de threads que le système peut gérer, et l'utiliser comme base pour le nombre de threads de votre application. devrait créer. Le seul défi ici est de trouver ces API; que vous passiez au niveau du système d'exploitation ou que vous recherchiez une bibliothèque tierce ou un SDK / API multiplateforme, cela dépend de vous et des plates-formes que vous essayez de prendre en charge.

Quelle est la meilleure façon d'aborder le développement de cette manière (compte tenu de toute API de threading multiplateforme) compte tenu des éléments suivants:

different numbers of cores
vastly different processing capabilities per core
A generally different systems architecture with eg. different

latences pour le cache, la RAM et l'accès aux E / S

À mon avis, aucune de ces choses ne devrait vous préoccuper. Votre préoccupation devrait être de construire votre jeu. Si vous rencontrez un goulot d'étranglement et décidez qu'il serait préférable de générer un thread séparé pour une tâche spécifique gourmande en processeur, puis générez le thread et laissez le système d'exploitation et d'autres logiciels de niveau inférieur décider comment manipuler le matériel pour gérer le threading.

Chiffrer
la source