wtorek, 17 stycznia 2017

Obliczanie Pi - przyśpieszone

A teraz obiecana przyśpieszona wersja programu obliczającego liczbę Pi metodą Monte Carlo:
Pierwotny program na moim laptopie wykonywał ok 1500 losowań na sekundę. Ten jest 1000 razy szybszy! Wykonuje około 1500000 losowań na sekundę. Składa się na to kilka modyfikacji:
  1. W obrębie procedury draw() wstawiona jest pętla wykonująca pewną liczbę losowań (zmienna nst) w każdym wywołaniu. Dzięki temu zmniejszamy czas obsługi okna odbywającej się w związku z każdym wywołaniem draw(). Zamiast 1500 takich operacji mamy trochę ponad 70, przy nst == 20000. Czyli program losuje punkty i wrzuca je na wewnętrzną reprezentację grafiki okna, a okno odświeża nie 1500, ale jedynie 75 razy na sekundę. To daje gigantyczną oszczędność!
  2. W procedurze setup() wyłączamy wygładzanie grafiki za pomocą noSmooth() .
    Skoro rysujemy pojedyncze punkty to jest ono zbędne, a nawet niepożądane. Ta modyfikacja daje jeszcze około pięciokrotne przyśpieszenie
  3. Zamiast losować składową koloru i odcień szarości dla wizualizowanych punktów używamy reszty z dzielenia (operator %). Jest to operacja dużo szybsza niż uzyskanie kolejnej liczby pseudolosowej, a efekt wizualny jest nieodróżnialny - i tak losujemy pozycje punktów, więc to że kolory mają sekwencyjne odcienie jest nie do zauważenia. Przy okazji oszczędzamy też liczbę wywołań generatora pseudolosowego co przy miliardach nawrotów pętli może mieć znaczenie (ale to temat na osobny post, a nawet kilka wpisów)
  4. Tak znaczące przyśpieszenie programu pozwala osiągnąć w rozsądnym czasie kilka miliardów losowań. I tu pojawia się problem, bo w zakresie liczby typu int (32 bity ze znakiem) mieści się zaledwie trochę ponad 2 miliardy. A potem, czyli przy kolejnym powiększeniu o 1, liczba ta się przewija i staje UJEMNA! Nie ma sensu dalej liczyć. Stąd sprawdzamy w programie kiedy nastąpi ten moment i wyłączamy dalsze wywołania pętli draw() za pomocą noLoop();
    Ale przedtem obliczamy uzyskaną wartość Pi i wyświetlamy w oknie graficznym czcionką o rozmiarze 18 pkt.


    Oto wynik działania:
Tak oto uzyskaliśmy bardzo szybki program, aczkolwiek jego dokładność nie jest oszałamiająca. Wynika to z ograniczeń zastosowanych typów - float i int. Można by dokładność zwiększyć używając pojemniejszych typów - na początek także standardowe double i long. Ale to by rodziło kolejne problemy, bo są to typy języka Java nie do końca wspierane przez Processing.
Tak więc o ich stosowaniu będzie innym razem.

Brak komentarzy:

Prześlij komentarz