Question

Je travaille sur un jeu RTS en C ++ destiné au matériel de poche (Pandora). Pour référence, le Pandora a un seul processeur ARM à ~ 600 MHz et tourne sous Linux. Nous essayons de nous contenter d’un bon système de transmission de messages (à la fois interne et externe), et c’est un nouveau territoire pour moi.

Il peut être utile de donner un exemple de message que nous aimerions transmettre. Une unité peut effectuer cet appel pour charger ses modèles en mémoire:

sendMessage ("model-loader", "load-model", my_model.path, model_id);

En retour, l’unité peut s’attendre à une sorte de message contenant un objet de modèle pour le model_id particulier, qui peut ensuite être transmis au système graphique. Veuillez noter que cette fonction sendMessage n'est en aucun cas finale. Cela reflète simplement ma compréhension actuelle des systèmes de transmission de messages, ce qui n’est probablement pas correct:)

D'après ce que je peux dire, il y a deux choix bien distincts. La première consiste à transmettre des messages en mémoire et à ne passer par le réseau que lorsque vous devez parler à un ordinateur externe. J'aime cette idée car les frais généraux semblent faibles, mais le gros problème ici est qu'il semble que vous deviez faire un usage intensif du verrouillage mutex sur vos files d'attente de messages. J'aimerais vraiment éviter un verrouillage excessif si possible. J'ai lu quelques manières d'implémenter des files d'attente simples sans verrouillage (en utilisant des opérations atomiques int ), mais celles-ci supposent qu'il n'y a qu'un seul lecteur et un seul écrivain pour une file d'attente. Cela ne semble pas utile dans notre cas particulier, car la file d'attente d'un objet aura plusieurs écrivains et un seul lecteur.

L’autre option consiste à accéder complètement à la couche réseau. Cela présente certains avantages amusants, tels que l’obtention gratuite du message asynchrone. Nous avons également la possibilité de transmettre des messages à d’autres machines en utilisant exactement les mêmes appels que pour les transmettre localement. Cependant, cette solution me trompe, probablement parce que je ne le comprends pas bien. Aurions-nous besoin d'un socket pour chaque objet qui va envoyer / recevoir des messages? Si c'est le cas, cela semble excessif. Un jeu donné aura des milliers d'objets. Pour un appareil un peu sous-développé, tel que le Pandora, je crains qu’un tel abus ne devienne notre goulet d’étranglement. Mais, je n'ai pas encore fait de tests, donc ce ne sont que des spéculations.

MPI semble être populaire pour la transmission de messages, mais il semble vraiment exagéré pour ce que nous voulons. Ce code ne va jamais toucher un cluster ni nécessiter de gros calculs.

Nous vous serions reconnaissants de bien comprendre quelles options nous avons pour le faire.

Était-ce utile?

La solution

Le réseau utilisera également le verrouillage. Ce sera juste là où vous ne pourrez pas le voir, dans le noyau du système d'exploitation.

Ce que je ferais, c’est de créer votre propre objet file d’attente de messages que vous pourrez réécrire selon vos besoins. Commencez simplement et améliorez-le au besoin. De cette façon, vous pouvez lui faire utiliser l’implémentation de votre choix dans les coulisses sans modifier le reste de votre code.

Examinez plusieurs implémentations que vous aimeriez peut-être faire à l'avenir et concevez votre API de manière à pouvoir toutes les gérer efficacement si vous décidez de les implémenter dans ces termes.

Si vous voulez que les messages passent très efficacement, jetez un coup d’œil à certains des micro-noyaux L4 open source. Ces gars-là ont mis beaucoup de temps dans la transmission rapide des messages.

Autres conseils

Comme il s’agit d’une petite plate-forme, il pourrait être utile de chronométrer les deux approches.

Toutefois, à moins d’un problème de grande vitesse, je choisirais toujours une approche plus simple à coder. Cela va probablement utiliser la pile réseau, car ce sera le même code, peu importe le lieu où se trouve le destinataire, et vous n'aurez pas à coder et déguer manuellement vos exclusions mutuelles, la mise en mémoire tampon des messages, les allocations, etc.

Si vous découvrez que c'est trop lent, vous pouvez toujours recoder le contenu local en utilisant la mémoire plus tard. Mais pourquoi perdre votre temps à le faire si vous n’êtes pas obligé de le faire?

Je suis d'accord avec la recommandation de Zan de transmettre les messages en mémoire chaque fois que possible.

Une des raisons est que vous pouvez passer des objets complexes en C ++ sans avoir besoin de les marshaler et les annuler (les sérialiser et les désérialiser).

Le coût de la protection de votre file d'attente de messages avec un sémaphore sera probablement inférieur au coût des appels de code réseau.

Si vous protégez votre file d'attente de messages avec un algorithme sans verrouillage (en utilisant des opérations atomiques comme vous l'avez dit vous-même), vous pouvez éviter beaucoup qu'un contexte ne bascule dans le noyau.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top