Czy zdarzyło Ci się kiedyś, że Twój program realizujący stosunkowo proste obliczenia wykonywał się bardzo długo? A może jakaś pętla spowodowała, że MATLAB przestał reagować na polecenie Ctr+c?
Przyczyną może być niezoptymalizowany pod kątem obliczeń wektorowych program. Okazuje się bowiem, że klasyczne podejście do programowania znane z języków niższego poziomu, gdzie na przykład do kopiowania elementów musimy używać pętli, nie jest wskazane w produkcie MathWorksa. MATLAB jest zoptymalizowany pod kątem obliczeń macierzowo-wektorowych i wykorzystanie tej cechy umożliwia uzyskanie uproszczenia programu, a przede wszystkim skrócenie czasu obliczeń. Zapraszam do lektury wpisu oraz zobaczenia filmu na Youtube dotyczącego tego tematu, link do którego znajduje się na końcu posta.
Alokacja pamięci i wektoryzacja obliczeń
Aby lepiej zobrazować problem, rozpatrzmy prosty przykład. Zadanie polega na wygenerowaniu N=100000 równomiernie rozłożonych liczb z zakresu od 0 do 1. W pierwszym odruchu wielu programistów sięga po pętle for:
for k = 1 : N x1(k) = k/N; % x1 jest powiększane w każdej iteracji end
Uzyskany czas obliczeń 0.01s.
W MATLABie nie jest to ani eleganckie ani efektywne obliczeniowo podejście. Powiększanie wektora lub macierzy o nowe elementy powoduje konieczność kopiowania całej zmiennej w nowy obszar pamięci. A to jest operacja czasochłonna. Jednak, jeżeli już używacie takiej struktury, to przed rozpoczęciem obliczeń należy zainicjować wektor, do którego będą wpisywane generowane wartości:
x1(1,N) = 0; for k = 1 : N x1(k) = k/N; end
Uzyskany czas obliczeń 0.001s, czyli 10 razy krócej niż w przypadku pierwszym.
Stosowanie pętli for do generowania elementów wektora nie jest jednak w MATLABie zalecane. Mamy tu do dyspozycji operator dwukropka, który jest zoptymalizowany pod kątem generacji wektorów. Jego użycie pozwala znacznie uprościć program oraz skrócić czas jego realizacji:
x3=[0.00001:0.00001:1];
Uzyskany czas obliczeń 0.0004s. To jest 25 razy szybciej niż w przypadku pierwszym!
Wyżej wymienione techniki nazywane są w MATLABie alokacją pamięci dla zmiennej oraz wektoryzacją obliczeń. Ich stosowanie umożliwia znaczące uproszczenie programu i przyspieszenie jego realizacji.
Wiarygodne czasy obliczeń
Przytoczone czasy realizacji obliczeń zostały wyznaczone za pomocą funkcji tic i toc. Ponieważ jednak na czas obliczeń może wpłynąć chwilowe obciążenie procesora przez inne procesy systemowe czy też programy działające w tle, to badanie danego fragmentu programu należy powtórzyć wielokrotnie, a za czas obliczeń przyjąć czas sumaryczny bądź wartość średnią z M powtórzeń programu. Badany program należy więc objąć dodatkową pętlą:
M = 1000; % liczba powtórzeń eksperymentu tic for p = 1 : M % Tutaj znajduje się badany program end toc
W ten sposób uzyskane wyniki, dla M=1000 powtórzeń są bardziej miarodajne i stabilne, niż dla jednego obiegu programu, który może zależeć od chwilowego obciążenia procesora. Dla tak skonstruowanego programu otrzymano następujące rezultaty:
Metoda 1: 11.00s
Metoda 2: 0.40s
Metoda 3: 0.06s
Jak widać korzyść ze stosowania alokacji pamięci i wektoryzacji w MATLABie jest ogromna i przynosi nawet kilkusetkrotne przyspieszenie czasu obliczeń!
Youtube
Jeżeli chcecie dowiedzieć się więcej na temat poprawnego pisania, efektywnych obliczeniowo programów zachęcam do obejrzenia tego filmu na moim kanale na Youtube. Pochwalcie się w komentarzach czy udało Wam się zoptymalizować Wasze programy!
Piotr Burnos
Dziękuję za ogromną wartość edukacyjną Twojego bloga 🙂
Dziękujemy za miłe słowa. Już niebawem kolejne wpisy 🙂