2012-03-02 23 views
5

Quindi sto essenzialmente cercando di implementare un'Aria Native Extension che esegue la simulazione fisica in C con le interfacce tramite Actionscript.Threading Box2D con pthreads

Ho passato un bel po 'di iterazioni che elencherò di seguito per interesse e sono a quello che penso possa essere il mio ultimo tentativo di farlo funzionare in un modo più performante.

In definitiva sto cercando aiuto su come impostare un ambiente di threading per eseguire la simulazione di Box2D su un thread separato e quindi eseguire il polling dello stato in AS3.

Metodi:

  1. Brute force:

In questo metodo ho semplicemente mettere in C da AS3 e dirgli di creare un mondo e passarlo alcune scatole da aggiungere al questo mondo. Ogni frame in AS3, chiamo in C per dire al mondo di Step, quindi eseguo un ciclo attraverso tutti i corpi del mondo, ottengo la loro posizione e rotazione, li converto in oggetti actionscript e li metto in un array actionscript e poi li rimando a AS3. Una volta lì, faccio un ciclo attraverso l'array di restituzione e assegna quei valori di rotazione e posizione ai miei sprite in modo che vengano aggiornati visivamente.

I risultati sono in realtà abbastanza buoni con circa 116 caselle aggiunte prima del framerate. Questo è paragonato a 30 box in una pura implementazione AS3. Nota che queste statistiche sono in modalità Debug. In modalità di rilascio, entrambi raggiungono circa 120 caselle. C'è poca differenza tra l'implementazione AS3 e l'implementazione dell'estensione nativa.

  1. ByteArray condivisione

Al fine di migliorare le prestazioni ho deciso che sarebbe una buona idea per cercare di limitare la quantità di dati che vengono schierato tra C e AS3 . Il supporto di ANE che condivide lo spazio di memoria di un array di byte e quindi vorrei inviare il ByteArray creato in AS3 a C e avere C semplicemente aggiornare ByteArray. Questo ci risparmia dal dover costruire oggetti AS3 in C e passarli indietro. Ogni frame, AS3 ha semplicemente bisogno di scorrere attraverso il suo ByteArray e vedere cosa C ha scritto in esso e quindi assegnare quei valori agli sprite per impostare lo stato visivo.

I risultati qui sono purtroppo circa lo stesso. I miglioramenti sono solo marginali.

  1. Impostazione Oggetto Diretto Da C

Un'altra cosa ANE di sono in grado di sta impostando la proprietà di un oggetto che vive in AS3. In questo senso ho mirato a eliminare il sovraccarico del passaggio dei dati in AS3, il looping dei corpi per raccogliere i dati in C e il looping in AS3 per assegnare i valori. Ho modificato direttamente il codice di Box2D in modo che quando i valori fossero cambiati scrivesse i nuovi valori di x, y, di rotazione direttamente sullo Sprite corrispondente.

I risultati sono sorprendenti a quantità molto ridotte di oggetti poiché la chiamata per impostare queste proprietà è ben al di sotto di un millisecondo. Il problema è che questo scala in modo lineare e intorno a circa 90 oggetti, il sovraccarico è troppo severo e le cose iniziano a rallentare.

  1. Threading

A questo punto ero un po 'perplesso. C'è un sovraccarico nei dati di marshalling, c'è un costo in C per l'iterazione e la costruzione dei dati da restituire e c'è un costo in AS3 per l'iterazione per assegnare valori agli sprite.

Ovviamente ci deve essere un compromesso quindi la mia soluzione attuale è la migliore che riesca a trovare per ora.

Sul lato AS3 chiamate in C per creare il vostro mondo, chiamate per aggiungere una casella a quel mondo e chiamate per dire a C che volete un aggiornamento dei vostri dati. Quando le scatole vengono create in AS3 ottengono un ID univoco e sono memorizzate in un dizionario con la chiave che rappresenta l'id.

Sul lato C, il mondo viene creato e viene generato un nuovo pthread per eseguire il passaggio. Simula essenzialmente il mondo su un altro thread. Dopo averlo fatto, assembla tutti i dati e li scrive in un doppio array. Quindi lo fa ancora e ancora e ancora. Semplicemente simula per sempre fondamentalmente sul proprio thread.

Quando chiamiamo in C per aggiungere una nuova casella, ho bisogno di creare una nuova casella e aggiungerla a quel mondo. Dal momento che il mondo sta facendo un passo questo potrebbe causare problemi, il che significa che ho bisogno di usare i mutex, ne sono abbastanza sicuro.

La stessa cosa quando chiamiamo per ottenere i valori aggiornati in AIR, voglio fare una memcpy dall'array di doubles nel mio AS3 bytearray e quindi passare attraverso il bytearray per impostare i valori sul visual.

I mutex mi davano fastidio così ho praticamente implementato la mia, che potete vedere qui sotto ... e ridere :)

Tuttavia funziona, semplicemente non veloce come vorrei anche. Verso il 90 rallentiamo di nuovo.

Qualcuno ha qualche idea o suggerimento? Sarebbe molto apprezzato!

codice C

Il parser stava comportando in modo ho incollato qui: http://pastebin.com/eBQGuGJX

Codice AS3

Stessa cosa con il parser. Ho incluso solo il metodo pertinente che riguarda ogni frame in AS3. http://pastebin.com/R1Qs2Tyt

+0

Ho la sensazione che questo è il sanguinamento bordo basta che non si trovano molta assistenza ovunque :) Sono anche perplesso sul motivo per cui le discussioni avrebbero aiutato. Poiché ogni passo del mondo ha bisogno delle informazioni dall'ultimo passaggio, non possono essere eseguite in parallelo, e l'esecuzione della parte C in un thread non aiuta se il collo di bottiglia è il trasferimento di informazioni su AS3. All'interno di una fase del mondo è possibile eseguire contemporaneamente piccole sezioni del processo, ma il guadagno in termini di prestazioni è piuttosto ridotto e il consenso generale sembra essere che sia più vantaggioso utilizzare core aggiuntivi per il rendering o qualcos'altro. – iforce2d

+0

Grazie iforce2d. Sì, non ero sicuro di ottenere una risposta di per sé, ma speravo di poter ulteriormente approfondire la discussione su approcci come questo o collegamenti a materiale rilevante per spiegazioni più approfondite. La mia speranza era che la simulazione potesse essere semplicemente eseguita lungo il proprio thread e il rendering sarebbe appena entrato e tirato l'ultima "istantanea" delle posizioni dell'oggetto e usarlo per renderizzare. – Jon

+0

+1 per la domanda/articolo molto interessante – Ryan

risposta

3

Mi ero dimenticato di avere questa domanda. Per fortuna l'ho capito.

L'idea di utilizzare mutex ecc. È stata sovradimensionata e non necessaria.

Poiché siamo in esecuzione in Flash, tutto viene eseguito nella thread principale. Il che significa che ogni flash "frame" gestirà in modo nativo qualsiasi supporto, quindi il nostro codice client che abbiamo scritto, quindi lo renderizzeremo sullo schermo e infine eseguiremo qualsiasi raccolta di dati inutili se necessario.

In realtà non ho bisogno di avere la sim fisica simulando per sempre, ho semplicemente bisogno di essere un passo avanti al mio codice cliente.

Quindi, ciò che accade ora è quando il client chiama in ANE per configurare il mondo, crea un nuovo thread che simula il mondo e torna immediatamente a Flash. Flash continuerà a eseguire il proprio lavoro eseguendo il resto del codice client e quindi il rendering e quindi GC.

Quindi su ciascun frame in Flash possiamo semplicemente chiamare in ANE per recuperare i risultati. Nel caso in cui il thread di simulazione non fosse terminato, attendiamo tramite un join, estraiamo i valori e li restituiamo a Flash. Assicurati di generare un'altra discussione per il passaggio successivo prima di tornare, naturalmente.

In questo modo stiamo massimizzando la nostra efficienza dal momento che la simulazione sta accadendo mentre Flash è occupato a fare altre cose su cui non abbiamo il controllo (come il rendering e GC).

La buona notizia è che le prestazioni quasi raddoppiano con questo approccio. Passando da circa 90 scatole in un'implementazione sincrona AS3 pura a circa 170 scatole in un approccio ANE filettato.

Il collo di bottiglia diventa infine l'iterazione attraverso i dati provenienti da ANE e l'assegnazione di tali valori agli oggetti di visualizzazione.

Spero che questo aiuti qualcun altro che cercava qualcosa di simile. Ne parlerò a FITC Toronto alla fine di aprile, quindi potrebbero esserci più informazioni e materiale che posso postare.

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