2012-03-02 16 views
5

Tak więc zasadniczo próbuję implementować AIR Native Extension, które wykonuje symulację fizyki w C za pomocą interfejsów za pomocą Actionscript.Threading Box2D z pthreads

Przeszedłem kilka iteracji, które podaję poniżej, dla dobra interesu i jestem w stanie, jak sądzę, być moją ostatnią próbą uzyskania tego działającego w bardziej wydajny sposób.

Ostatecznie szukam pomocy w tym, jak powinienem stworzyć środowisko wątków do uruchamiania symulacji Box2D w osobnym wątku, a następnie odpytywania dla stanu w AS3.

Metody:

  1. brute force:

W tej metodzie po prostu zadzwonić do C z AS3 i poinformować go, aby stworzyć świat i przekazać niektóre okna, aby dodać do ten świat. Każda klatka w AS3, wzywam C, aby przekazać światu Krokowi, a następnie przejrzeć wszystkie ciała na Świecie, uzyskać ich pozycję i rotację, przekonwertować je na obiekty actionscript i umieścić je w tablicy actionscript, a następnie wysłać z powrotem do AS3. Tam przechodzę przez zwrotną tablicę i przypisuję te wartości pozycji i rotacji do moich ikonek, aby były wizualnie aktualizowane.

Wyniki są całkiem przyzwoite, ponieważ około 116 pól jest dodawanych przed chwilą cierpienia klatek na sekundę. Jest to porównywane z 30 pudełkami w czystej implementacji AS3. Zwróć uwagę, że te statystyki są w trybie debugowania. W trybie zwolnienia obaj osiągają około 120 skrzynek. Istnieje niewielka różnica między implementacją AS3 a implementacją Native Extension.

  1. ByteArray Sharing

W celu poprawy wydajności postanowiłem, że będzie to dobry pomysł, aby spróbować ograniczyć ilość danych jest zgromadzona w poprzek C i AS3 . Obsługa ANE współużytkuje przestrzeń pamięci tablicy bajtów, więc wysyłam ByteArray utworzony w AS3 do C i mam C po prostu aktualizuję ByteArray. To oszczędza nam konieczności konstruowania obiektów AS3 w C i przekazywania ich z powrotem. Każda klatka, AS3 musi po prostu iterować przez ByteArray i zobaczyć, co napisała C, a następnie przypisać te wartości do duszków, aby ustawić stan wizualny.

Wyniki tutaj są niestety mniej więcej takie same. Ulepszenia są tylko marginalne.

  1. bezpośrednie Otoczenie obiektu z C

Inną rzeczą ANE są zdolne jest ustawienie właściwości obiektu, który mieszka w AS3. W tym sensie miałem na celu wyeliminowanie narzutu przekazywania danych do AS3, przepuszczanie przez ciała w celu zbierania danych w C i przepuszczania w AS3 w celu przypisania wartości. Bezpośrednio zmodyfikowałem kod Box2D, aby po zmianie jego wartości zapisywać nowe wartości x, y, rotacji bezpośrednio na odpowiednim Sprite.

Wyniki są niesamowite przy bardzo małych ilościach obiektów, ponieważ wywołanie do ustawienia tych właściwości jest znacznie poniżej milisekundy. Problem polega na tym, że skaluje się liniowo i około 90 obiektów, a narzut jest zbyt poważny, a rzeczy zaczynają zwalniać.

  1. Threading

W tym momencie byłem trochę zakłopotany. W danych konfiguracyjnych jest dużo kosztów, w C jest koszt za iterację i skonstruowanie danych do zwrócenia, aw AS3 jest koszt dla iteracji, aby przypisać wartości do ikonek.

Oczywiście musi istnieć kompromis, więc moje obecne rozwiązanie jest najlepsze, na jakie mogę teraz wymyślić.

Po stronie AS3 dzwonisz do C, aby stworzyć swój świat, zadzwoń, aby dodać pole do tego świata, i zadzwoń, aby powiedzieć C, że chcesz odświeżyć swoje dane. Gdy pola są tworzone w AS3, otrzymują unikalny identyfikator i są przechowywane w słowniku z kluczem będącym identyfikatorem.

Po stronie C tworzony jest świat i nowy krok pthread jest tworzony w celu wykonania kroku. Zasadniczo symulowanie świata w innym wątku. Po jego wykonaniu gromadzi wszystkie dane i zapisuje je w podwójnej tablicy. Potem robi to znowu i znowu i znowu. Po prostu na zawsze symuluje swoją własną nić.

Kiedy dzwonimy do C, aby dodać nowe pudełko, muszę utworzyć nowe pudełko i dodać je do tego świata. Ponieważ świat jest Stepping, może to powodować problemy, co oznacza, że ​​muszę używać muteksów, jestem prawie pewien.

To samo, gdy wywołujemy, aby odświeżyć wartości w środowisku AIR, będę chciał zrobić memcpy z tablicy dubletów w moim AS3 bytearray, a następnie przechodzić przez bytearray, aby ustawić wartości wizualne.

W muteksy dawali mi kłopotów, więc w zasadzie realizowany mój własny, który można zobaczyć poniżej ... i śmiać :)

Jednak to działa, po prostu nie tak szybko, jak bym się spodoba. Około 90 znowu zwalniamy.

Ktoś ma jakieś myśli lub wskazówki? Byłoby to bardzo docenione!

C Kod

Parser zachowywał się tak i wklejeniu go tutaj: http://pastebin.com/eBQGuGJX

AS3 Kod

samo z parsera. Zawarłem tylko odpowiednią metodę dotyczącą każdej ramki w AS3. http://pastebin.com/R1Qs2Tyt

+0

Mam wrażenie, to jest krwawienie krawędzi tyle, że nie znajdziesz nigdzie dużo pomocy :) Jestem też zdziwiony, dlaczego wątki pomoże. Ponieważ każdy krok na świecie potrzebuje informacji z ostatniego kroku, nie można ich uruchomić równolegle, a uruchomienie części C w wątku nie pomoże, jeśli wąskim gardłem jest przekazanie informacji do AS3. W ramach kroku światowego możliwe jest równoczesne wykonywanie niewielkich sekcji procesu, ale przyrost wydajności jest niewielki, a ogólna zgoda wydaje się, że bardziej korzystne jest użycie dodatkowych rdzeni do renderowania lub czegoś innego. – iforce2d

+0

Dzięki iforce2d. Tak, nie byłem pewien, czy dostanę odpowiedź per se, ale miałem nadzieję, że będę mógł dalej prowadzić dyskusję na temat takich podejść lub powiązać z odpowiednim materiałem w celu uzyskania bardziej dogłębnych wyjaśnień. Moja nadzieja była taka, że ​​symulacja może przebiegać wzdłuż własnej nitki, a rendering po prostu wskoczyłby i pobrał najnowsze "migawki" pozycji obiektu i użył go do renderowania. – Jon

+0

+1 za bardzo interesujące pytanie/artykuł – Ryan

Odpowiedz

3

Zapomniałem, że mam to pytanie. Na szczęście to rozgryzłem.

Pomysł użycia muteksów itp. Został przebudowany w pierwszej kolejności i niepotrzebny.

Ponieważ używamy Flasha, wszystko działa w głównym wątku. Co oznacza, że ​​dla każdego "klatki" flash będzie natywnie obsługiwał dowolny nośnik, następnie nasz kod klienta, który napisaliśmy, a następnie renderuje się na ekran i na koniec wyszukuje śmieci w razie potrzeby.

Nie potrzebuję symulować symulacji fizyki na zawsze, po prostu muszę być o krok przed moim kodem klienta.

To, co dzieje się teraz, gdy klient dzwoni do ANE, aby skonfigurować świat, tworzy nowy wątek, który symuluje świat i wraca natychmiast z powrotem do Flash. Flash będzie nadal wykonywać swoją pracę polegającą na wykonywaniu reszty kodu klienta, a następnie renderowaniu, a następnie GC.

Następnie w każdej klatce Flash możemy po prostu wywołać ANE, aby pobrać wyniki. W przypadku, gdy wątek Symulacji nie został zakończony, czekamy przez połączenie, wyodrębniamy wartości i zwracamy je do Flasha. Upewnij się, że odrodzisz kolejny wątek w następnym kroku, zanim powrócisz.

W ten sposób maksymalizujemy naszą wydajność, ponieważ symulacja ma miejsce, podczas gdy Flash jest zajęty wykonywaniem innych rzeczy, nad którymi nie mamy kontroli (jak renderowanie i GC).

Dobrą wiadomością jest to, że wydajność niemal podwaja się z tym podejściem. Przechodzenie z około 90 pudełek w synchronicznej czystej implementacji AS3 do około 170 pudeł w podejściu ANE z gwintem.

Wąskie gardło ostatecznie staje się iteracją poprzez dane wracające z ANE i przypisywania tych wartości do obiektów wyświetlanych.

Mam nadzieję, że pomoże to komuś, kto szuka czegoś podobnego. Będę mówił o tym na FITC Toronto pod koniec kwietnia, więc może być więcej informacji i materiałów, które mogę opublikować.

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