Tak, zdarza się. Dzisiaj wyjątkowo krótka notka, ale dosyć ważna z punktu widzenia prototypowego silnika. Otóż, okazuje się, iż zastępowanie algorytmów już istniejących swoimi nie zawsze okazuje się skuteczne. W czym rzecz?
Jak pewnie niektórzy pamiętają, dla wielkich (ale o niezdefiniowanym z góry rozmiarze) tablic typu float, stosowanych na przykład dla wierzchołków, używałem swojej struktury CArrayFloat, która była odchudzoną wersją STL-owskiego std::vector<float>, czyli samorozszerzalną tablicą typu zmiennoprzecinkowego. Nie ukrywam, że podejrzewałem, iż moje rozwiązanie jest wolniejsze od standardowego kontenera, ale nie sądziłem, że aż tak w takim stopniu.
Do wykonanie krótkiego testu podkusił mnie fakt, że wszystkie programy testujące mój framework działały wolniej przy używaniu CArrayFloat. Wprawdzie od ostatniej linijku kodu pisanego z myślą o Yeście minęło już troszkę czasu, ale od czasu do czasu mam takie dziwne pobudki, aby coś sprawdzić. Kiedyś też Toxic (pozdrawiam) wyraził swoje wątpliwości odnośnie moich porównań efektywności.
Test przebiegał następująco:
- Do dwóch zmiennych (jedna typu std::vector<float>, a druga CArrayFloat) dodaj N wartości wynoszących i / (0.5f + 0.32432f * 0.123f), gdzie i to licznik pętli
- Z obu zmiennych usuń wszystkie elementy
Mierzone oczywiście były czasy tych operacji. Wyniki okazały się potworne (dane w sekundach – 0 oznacza czas bardzo bliski zeru):
| 10000 elementów | Wstawienie | Usunięcie |
| std::vector<float> | 0 | 0 |
| CArrayFloat | 0,156 | 0,156 |
| 100000 elementów | Wstawienie | Usunięcie |
| std::vector<float> | 0 | 0 |
| CArrayFloat | 14,414 | 14,056 |
| 1000000 elementów | Wstawienie | Usunięcie |
| std::vector<float> | 0,016 | 0 |
| CArrayFloat | Błąd | Błąd |
Nie dość, że zmienna typu CArrayFloat była nieporównywalnie wolniejsza od C++-owego wektora, to jeszcze dla miliona elementów nastąpiło przepełnienie stosu i aplikację omotał tzw. Błąd Straszny i Wielki. W tych samych warunkach wektor poradził sobie doskonale, uzyskując czasy asymptotycznie bliskie zeru.
Dlaczego zatem pisałem własną klasę? Z tego względu, iż w początkach mojej zabawy z językiem C++, głównym sprawcą “wywalania” się aplikacji był właśnie kontener wektorowy. A jako, że byłem młody i głupi, to nie umiałem sobie z tym poradzić w żaden sposób, więc jak przyszło do pisania czegoś większego (kolizje), to uznałem, że napiszę własny kod. Podejrzewałem troszkę, że będzie on wolniejszy, ale przynajmniej będzie mój, mój i mój. Co z tego wyszło?
Rzeczywiście, z CArrayFloat jestem całkiem zadowolony implementacyjnie – zawsze czegoś nowego człowiek się uczy, a programowanie przynosi wiele radości. Nie da się jednak ukryć, że w transportowaniu algorytmów z frameworka w nowe środowisko (jakiś silnik lub coś innego) nie zrezygnuję już z std::vector. To się po prostu nie opłaca.
Zatem, jeśli ktoś mi kiedyś wytknął błąd przy CArrayFloat – teraz oficjalnie się przyznaję do tego, że miał rację. Tym niemniej zachęcam do spróbowania swoich sił w napisaniu czegoś podobnego, ale duuuuuużo szybszego.
Pozdrawiam i dziękuję – SceNtriC.
0 komentarze:
Prześlij komentarz