2012-03-02 2 views
5

Donc j'essaie essentiellement d'implémenter une extension native AIR qui fait la simulation physique en C avec des interfaces via Actionscript.Threading Box2D avec pthreads

Je suis passé par plusieurs itérations que je vais énumérer ci-dessous pour l'intérêt de l'intérêt et je suis à ce que je pense que pourrait être ma dernière tentative pour que cela fonctionne d'une manière plus performante. En fin de compte, je cherche de l'aide dans la façon dont je devrais mettre en place un environnement de threading pour exécuter la simulation de Box2D sur un thread séparé, puis interroger l'état dans AS3.

Méthodes:

  1. Brute Force:

Dans cette méthode, j'appelle simplement en C de AS3 et lui dire de créer un monde et passer quelques boîtes à ajouter ce monde. Chaque image dans AS3, j'appelle C pour dire au monde de faire un pas, puis faire une boucle sur tous les corps du monde, obtenir leur position et leur rotation, les convertir en objets actionscript et les placer dans un tableau d'actionscript, puis renvoyer AS3. Une fois là-bas, je fais une boucle sur le tableau retourné et j'assigne ces valeurs de position et de rotation à mes sprites afin qu'elles se mettent à jour visuellement.

Les résultats sont en fait assez décent avec environ 116 boîtes ajoutées avant que le framerate ne souffre. Ceci est comparé à 30 boîtes dans une implémentation AS3 pure. Notez que ces statistiques sont en mode débogage. En mode release, ils font tous les deux environ 120 boîtes. Il y a peu de différence entre l'implémentation AS3 et l'implémentation Native Extension.

  1. ByteArray Partage

Afin d'améliorer les performances, j'ai décidé que ce serait une bonne idée d'essayer de limiter la quantité de données mobilisées dans C et AS3 . Le support d'ANE partageant l'espace mémoire d'un tableau d'octets et donc j'enverrais le ByteArray créé dans AS3 en C et je ferais simplement mettre à jour le ByteArray. Cela nous évite d'avoir à construire des objets AS3 en C et de les renvoyer. A chaque trame, AS3 doit simplement parcourir son ByteArray et voir ce que C a écrit dedans, puis assigner ces valeurs aux sprites pour définir l'état visuel.

Les résultats ici sont malheureusement à peu près les mêmes. Les améliorations ne sont que marginales.

  1. Réglage objet direct depuis C

est une autre chose ANE sont capables de se définir la propriété d'un objet qui vit en AS3. Dans ce sens, je visais à éliminer le surcoût de renvoi de données à AS3, la boucle à travers les corps pour collecter des données dans C et la boucle dans AS3 pour assigner les valeurs. J'ai directement modifié le code Box2D de sorte que lorsque les valeurs étaient modifiées, il écrivait les nouvelles valeurs de rotation x, y, directement sur le Sprite correspondant.

Les résultats sont étonnants pour de très faibles quantités d'objets puisque l'appel pour définir ces propriétés est bien inférieur à une milliseconde. Le problème est que ceci évolue linéairement et qu'il y a environ 90 objets, les frais généraux sont trop élevés et les choses commencent à ralentir.

  1. Threading

À ce stade, j'étais un peu perplexe. Il y a un surcoût dans les données de marshalling, il y a un coût en C pour l'itération et la construction des données à retourner et il y a un coût dans AS3 pour l'itération d'assigner des valeurs aux sprites.

Évidemment, il doit y avoir un compromis de sorte que ma solution actuelle est la meilleure que je peux trouver pour l'instant. Du côté AS3, vous appelez C pour créer votre monde, appelez pour ajouter une boîte à ce monde, et appelez pour dire à C que vous voulez un rafraîchissement de vos données. Lorsque les boîtes sont créées dans AS3, elles reçoivent un identifiant unique et sont stockées dans un dictionnaire dont la clé est l'identifiant. Sur le côté C, le monde est créé et un nouveau pthread est créé pour faire le Step. Essentiellement simulant le monde sur un autre fil. Après l'étape, il rassemble toutes les données et les écrit dans un double tableau. Ensuite, il le fait encore et encore et encore. Il simule simplement pour toujours sur son propre fil.

Lorsque nous appelons C pour ajouter une nouvelle boîte, je dois créer une nouvelle boîte et l'ajouter à ce monde. Puisque le monde est en marche, cela pourrait causer des problèmes, ce qui signifie que je dois utiliser des mutex. Même chose quand nous appelons pour obtenir les valeurs rafraichies dans AIR, je veux faire un memcpy de la matrice de doubles dans mon bytearray AS3 et ensuite faire une boucle dans le bytearray pour définir les valeurs sur le visuel.

Les mutex me donnaient du mal donc je essentiellement mis en œuvre ma propre que vous pouvez voir ci-dessous ... et rire :)

Cependant, il fonctionne, mais pas aussi vite que je le voudrais aussi. Vers 90, nous ralentissons à nouveau.

Quelqu'un at-il des idées ou des pointeurs? Ce serait grandement apprécié!

Code C

L'analyseur a agi de façon à ce que j'ai collé ici: http://pastebin.com/eBQGuGJX

Code AS3

Même chose avec l'analyseur. J'ai seulement inclus la méthode pertinente traitant de chaque image dans AS3. http://pastebin.com/R1Qs2Tyt

+0

J'ai le sentiment saigne bord assez que vous ne trouverez pas beaucoup d'aide partout :) Je suis aussi perplexe pourquoi les discussions contribueraient. Puisque chaque étape du monde a besoin des informations de la dernière étape, elles ne peuvent pas être exécutées en parallèle, et l'exécution de la partie C dans un thread propre n'aide pas si le goulot d'étranglement est le transfert d'informations vers AS3. Dans une étape mondiale, il est possible de faire de petites sections du processus simultanément, mais le gain de performance est assez faible et le consensus général semble être qu'il est plus avantageux d'utiliser des cœurs supplémentaires pour le rendu ou autre chose. – iforce2d

+0

Merci iforce2d. Ouais je n'étais pas sûr d'avoir une réponse en soi, mais j'espérais potentiellement approfondir la discussion sur des approches comme celle-ci ou des liens vers des documents pertinents pour des explications plus approfondies. Mon espoir était que la simulation puisse être juste en cours d'exécution sur son propre thread et que le rendu apparaîtrait juste et tirerait le dernier "snapshot" des positions d'objet et l'utiliserait pour le rendu. – Jon

+0

+1 pour une question/article très intéressant – Ryan

Répondre

3

J'avais oublié que j'avais cette question. Heureusement, je l'ai compris.

L'idée d'utiliser des mutex etc a été sur-machinée en premier lieu et inutile.

Depuis que nous tournons en Flash, tout tourne dans le fil principal. Ce qui signifie que pour chaque "frame" flash, nativement traiter n'importe quel média, alors notre code client que nous avons écrit, puis en fait rendre à l'écran et enfin faire une collection de place si nécessaire.

Je n'ai pas vraiment besoin d'avoir la simulation de physique simulant pour toujours, je dois simplement avoir une longueur d'avance sur mon code client.

Ce qui se passe maintenant, c'est lorsque le client appelle l'ANE pour configurer le monde, il crée un nouveau thread qui simule le monde et revient immédiatement à Flash. Flash continuera à faire son travail d'exécution du reste du code client, puis de rendu et ensuite GC.

Ensuite, sur chaque image dans Flash, nous pouvons simplement appeler l'ANE pour récupérer les résultats. Dans le cas où le thread de simulation n'était pas terminé, nous attendons via une jointure, extraire les valeurs et les renvoyer à Flash. Assurez-vous de générer un autre thread pour la prochaine étape avant de revenir bien sûr. De cette façon, nous maximisons notre efficacité puisque la simulation est en cours alors que Flash est occupé à faire d'autres choses que nous n'avons pas le contrôle (comme le rendu et le GC). La bonne nouvelle est que les performances doublent presque avec cette approche. Passage d'environ 90 boîtes dans une implémentation AS3 synchrone pure à environ 170 boîtes dans une approche filetée ANE. Le goulot d'étranglement devient finalement l'itération à travers les données revenant de l'ANE et assignant ces valeurs aux objets d'affichage. J'espère que cela aidera quelqu'un d'autre qui cherchait quelque chose de similaire. J'en parlerai au FITC de Toronto à la fin d'avril, donc il se peut qu'il y ait plus de renseignements et de documents que je puisse poster.

http://www.fitc.ca/events/presentations/presentation.cfm?event=124&presentation_id=1973