W05 - Złożoność pamięciowa

22
Pierwszym celem analizy algorytmów bylo wykazywanie poprawności algorytmów. Z chwilą pojawienia się komputerów większą wagę przywiązywano do szacowania zajętości pamięci, niż Podstawy analizy algorytmów do analizy zlożoności czasowej. Wraz z rozwojem technologii pólprzewodnikowej, kwestie zlożoności pamięciowej mają znaczenie drugorzędne. Liczbę komórek pamięci zajmowanych przez program, wyrażoną asymptotycznie, nazywamy zlożonością pamięciową. Liczba ta zależy od implementacji. Program wymaga pamięci komputera na rozkazy, stale i zmienne oraz na dane. Dane wejściowe mogą być zorganizowane w struktury danych mające żne zapotrzebowania na pamięć.

Transcript of W05 - Złożoność pamięciowa

Page 1: W05 - Złożoność pamięciowa

Pierwszym celem analizy algorytmów było wykazywaniepoprawności algorytmów. Z chwilą pojawienia się komputerówwiększą wagę przywiązywano do szacowania zajętości pamięci, niż

Podstawy analizy algorytmów

do analizy złożoności czasowej. Wraz z rozwojemtechnologiipółprzewodnikowej, kwestie złożoności pamięciowej mająznaczenie drugorzędne.

Liczbę komórek pamięci zajmowanych przez program,wyrażoną asymptotycznie, nazywamyzłożonością pamięciową.Liczba ta zależy od implementacji. Programwymaga pamięcikomputera na rozkazy, stałe i zmienne oraz na dane. Danewejściowe mogą być zorganizowane wstruktury danychmająceróżnezapotrzebowanianapamięć.

Page 2: W05 - Złożoność pamięciowa

Program może używać pamięci pomocniczej do organizacjiobliczeń. Jeśli pamięć pomocnicza jest stała względem rozmiarudanychn, to mówimy, że algorytmdziała w miejscu. Termin tenjest często używany w odniesieniu do algorytmówsortowania, októrych mówi się też, że działają in situ.

Podstawy analizy algorytmów

Mówiąc o liczbie komórek, nie precyzujemy rozmiaru jednejkomórki. Jeśli zapotrzebowanie na pamięć zależy nie tylko odrozmiaru danych, ale i od szczególnego układu tych danych, tomożemy mówić o oczekiwanejoczekiwanej złożonościzłożoności pamięciowejpamięciowej i złożonościzłożonościpamięciowejpamięciowej najgorszegonajgorszego przypadkuprzypadku.

Page 3: W05 - Złożoność pamięciowa

function reverse(A[0..n])

begin

Przykład zamiany prostego algorytmu na algorytm in situ

Przypuśćmy, że chcemy odwrócić tablicę składającą się z nelementów. Jeden z prostych sposobów jest taki:

Podstawy analizy algorytmów

begin

allocate B[0..n]

for i := 0 to n do B[n – i] := A[i]

return B

end;

Page 4: W05 - Złożoność pamięciowa

Podstawy analizy algorytmów

Niestety to wymaga O(n) miejsca do stworzenia tablicyB, aalokacja jest najczęściej wolną operacją. Jeśli nie potrzebujemydłużej A, to możemy w miejscu tego zapisać własne odwrócenieużywając poniższego algorytmuin situ:

function ReverseInPlace(A[0..n])

begin

for i := 0 to floor(n/2) do

swap(A[i], A[n–i])

end;

Page 5: W05 - Złożoność pamięciowa

Dla niektórych problemówistnieje kompromis pomiędzyzłożonością czasową i pamięciową. Dla pewnego problemuPmogą istnieć dwa algorytmy, mianowicie algorytmAl mającyzłożoność pamięciową O(n) i algorytm A2 osiągający złożonośćczasową O(n2). Badacze usiłują udowodnić, że sprawność każdegoalgorytmu spełnia pewne równanie, które wiąże pesymistycznązłożoność czasową T i złożoność pamięciową najgorszego

Podstawy analizy algorytmów

złożoność czasową T i złożoność pamięciową najgorszegoprzypadku S z rozmiarem danych wejściowych n. Typowymzagadnieniemjest pytanie:

- czy dla pewnych problemówwielomianowych, jak np.badanie spójności grafu, można zmniejszyć zapotrzebowanie napamięć roboczą do rozmiarów subliniowych, zachowującwielomianowość złożoności czasowej?

Page 6: W05 - Złożoność pamięciowa

Przypuśćmy, że jako zarówno dolne, jak i górne ograniczeniełącznej złożoności czasowo-pamięciowej pewnego zadania ustalonorównanie:

Podstawy analizy algorytmów

)log( 232 nnTS Θ=⋅

Jeżeli jesteśmy skłonni zużyć O(n3) czasu, to możemyrozwiązać zadanie używając tylko O(logn) pamięci. Jeśli natomiastnalegamy na poświęcenie nie więcej niż O(n2) czasu, to będziemypotrzebowali O(√n·logn) pamięci.

)log( nnTS Θ

¯

Page 7: W05 - Złożoność pamięciowa

Ciekawymzagadnieniemjest minimalizacja liczby komórekprzeznaczonych na zmienne programu. Minimalizację takąmożna przeprowadzić opierając się na analizie tzw. grafuniezgodności, którego wierzchołkami są zadeklarowanezmienne, a krawędziami związki informacyjne między nimi.Oszczędność pamięci uzyskujemy wówczas, gdy kilku

Podstawy analizy algorytmów

Oszczędność pamięci uzyskujemy wówczas, gdy kilkuzmiennym przyporządkowana jest jedna i ta sama komórkapamięci. Oszczędność pamięci jest niewielka, gdy zmiennezajmują pojedyncze komórki, lecz ma ogromne znaczenie, gdysą one tablicami. Analizę grafu niezgodności możnaprzeprowadzićmetodamikolorowania grafu.

Page 8: W05 - Złożoność pamięciowa

Z pojęciem struktury danychzwiązane jest pojęcie danychistotnych, tzn. takich, które nie mogą być pominięte w trakciedziałania algorytmu, ponieważ zignorowanie ich mogłobywypaczyć wynik. Ściślej, będziemy mówili,że rozważane zadanieman danych istotnych, jeśli istnieją dane I = (d1, d2, ..., dn) ∈ Dn,dla których zmiana dowolnej ze składowychdi, i = 1, 2, ..., npowodujezmianę wyniku. Na przykład w problemieobliczania

Podstawy analizy algorytmów

powodujezmianę wyniku. Na przykład w problemieobliczaniaśladu macierzy kwadratowej, czyli sumy elementówleżących nagłównej przekątnej, nieistotne są wszystkie elementy leżące pozagłówną przekątną. Jeżeli struktura danych zawiera wyłącznie daneistotne, to złożoność pamięciowa ogranicza od dołu złożonośćczasową z dokładnością do stałej proporcjonalności.

Page 9: W05 - Złożoność pamięciowa

Dowodzi się, że jeżeli algorytm ma n danych istotnych, tominimalna liczba działań dwuargumentowych wynosin/2. Wynikato stąd, że dowolny algorytmbędzie wymagał odwołania sięprzynajmniej raz do każdej komórki pamięci po to tylko, abywszystkie istotne elementy struktury danych zostałyuwzględnione. Zatem jeżeli strukturadanychzawierawyłącznie

Podstawy analizy algorytmów

uwzględnione. Zatem jeżeli strukturadanychzawierawyłączniedane istotne, to złożoność pamięciowa ogranicza od dołuzłożoność czasową z dokładnością do stałej proporcjonalności.

Page 10: W05 - Złożoność pamięciowa

Z drugiej strony istnieje proste oszacowanie górnezłożoności czasowej algorytmów. NiechC będzie maksymalnąliczbą różnych wartości możliwych do zapisania w pojedyńczejkomórce pamięci. Jeżeli algorytmma złożoność pamięciową S,to liczba wszystkich możliwych stanów jego pamięci nieprzekraczaCS. Stany te nie mogą powtarzać się w trakciewykonywania algorytmu, bo inaczej nastąpiłoby zapętlenie.

Podstawy analizy algorytmów

wykonywania algorytmu, bo inaczej nastąpiłoby zapętlenie.Zatemdla każdego algorytmu musi zachodzić:

Jeśli złożoność pamięciowaS jest logarytmiczna, np. logn, tooszacowanieCS naT staje się Clogn = nlogC, czyli wielomianowe.

SCTS ≤≤

Page 11: W05 - Złożoność pamięciowa

W praktyce istnieje kilka metod obniżania złożonościpamięciowej algorytmów. Pięć podstawowych sposobówograniczania wykorzystania pamięci roboczej programu:

1. Wielokrotne obliczanie wartości.Pamięć potrzebna do przechowywaniadanego obiektu może

Podstawy analizy algorytmów

Pamięć potrzebna do przechowywaniadanego obiektu możezmniejszyć się gwałtownie, jeśli nie zapamiętamy go, a zamiasttego będziemy obliczać jego wartość za każdymrazem, gdy będzieona potrzebna. Tablicę liczb pierwszych można zastąpić procedurąsprawdzającą, czy jakaś liczba naturalna jest liczbą pierwszą.Czasami, zamiast pamiętać cały obiekt, przechowujemy jedynieprogram, który go generuje i wartość startową generatora,określającą ten konkretny obiekt.

Page 12: W05 - Złożoność pamięciowa

2. Stosowanie struktur rozproszonych.Macierz rozrzedzonato taka tablica, w której większość elementówma tę samą wartość. Różnorodne tablice, macierze, grafy używanew programach są często strukturami rozproszonymi. Do ichimplementacji można używać specjalnych struktur listowych ozłożoności pamięciowej O(m), gdzie m jest liczbą elementów

Podstawy analizy algorytmów

złożoności pamięciowej O(m), gdzie m jest liczbą elementówniezerowych.

Page 13: W05 - Złożoność pamięciowa

3. Komprymowanie danych.Koncepcje umożliwiające ograniczanie pamięci przez stosowaniekompresji danych pochodzą z teorii informacji. Jeżeli elementymacierzy rzadkiej przyjmują tylko dwie wartości, to możemyzapamiętać je w postaci upakowanej na bitach. Podobnie dwiecyfry dziesiętne a i b można zapisać w jednymbajcie za pomocąliczby n = 10a + b. Do odkodowania informacji służą wówczasdwie instrukcje:

Podstawy analizy algorytmów

a := n div 10;

b := n mod 10;

W ten sposób osiągamy oszczędność 50%, co ma istotneznaczenie, gdy takich liczb jest bardzo dużo.

dwie instrukcje:

Page 14: W05 - Złożoność pamięciowa

4. Strategie przydziału pamięci.Czasami ilość dostępnej pamięci nie jest tak ważna jak sposóbjej wykorzystania. Do optymalizacji przydziału pamięci stosujesię takie techniki, jak dynamiczny przydział pamięci, rekordyzmiennej długości, odzyskiwanie pamięci i dzielenie pamięci.

Podstawy analizy algorytmów

Page 15: W05 - Złożoność pamięciowa

Jeżeli mamy dwie macierze symetryczneA i B o rozmiarachn × n, przy czymobie mają zera na głównej przekątnej, to możemyprzechowywać tylko macierz trójkątną każdej z nich.Możemy zatem pozwolić, aby obie tablice dzieliły przestrzeńmacierzy kwadratowejC[l...n], której jeden z rogówwyglądałbynastępująco:

Podstawy analizy algorytmów

0A[4,3]A[4,2]A[4,1]

B[3,4]0A[3,2]A[3,1]

B[2,4]B[2,3]0A[2,1]

B[1,4]B[1,3]B[1,2]0

Wówczas do elementuA[i, j] odwołujemy się za pomocą:C[max(i, j), min(i, j)]i analogicznie dla B, przestawiwszy jedynie min i max.

Page 16: W05 - Złożoność pamięciowa

5. Licznik probabilistyczny.Licznik probabilistyczny jest mechanizmem, który nan bitachpamięci pozwala zliczać wartości przekraczające 2n – 1. W tymcelu musimy zaimplementować 3 procedury: init(c), tick(c) icount(c), gdziec oznacza rejestrn-bitowy.

Wywołanie count(c) zwraca przybliżoną liczbę wywołań

Podstawy analizy algorytmów

Wywołanie count(c) zwraca przybliżoną liczbę wywołańprocedury tick(c) od czasu ostatniego wywołania proceduryinicjalizacyjnej init(c). Innymi słowy, init zeruje licznik, tickdodaje doń 1, a count podaje jego aktualną wartość. Zakrestakiego licznika możemy zwiększyć do 22n–1 – 1.

Page 17: W05 - Złożoność pamięciowa

Idea polega na utrzymywaniu w licznikuc oszacowania niefaktycznej liczby zdarzeń, lecz logarytmu dwójkowego z tejwartości. Dokładniej, count(c) zwraca 2c–1, czyli count(0) = 0.Natomiast implementacja tick(c) jest nieco bardziejskomplikowana. Przyjmijmy,że 2c–1 jest dobrymoszacowaniemwartości tick(c). Po dodatkowymtyknięciu zegara oszacowaniewinno wynosić 2c, ale to nie jest zgodne z ideą licznika

Podstawy analizy algorytmów

winno wynosić 2c, ale to nie jest zgodne z ideą licznikaprobabilistycznego, gdyż dodajemy 1 doc z pewnym prawdo-podobieństwemp << 1. Dlatego nasze oszacowanie wynosi 2c+1–1z prawdopodobieństwem p i pozostaje 2c–1 z prawdo-podobieństwem 1–p. Wartość oczekiwana licznika jest więcrówna:

122)1)(12()12( 1 −+=−−+−+ppp cccc

Page 18: W05 - Złożoność pamięciowa

Przyjęcie p = 2−c nadaje jej wartość 2c. Poniższe trzy procedury implementują ideę licznika probabilistycznego:

procedure init(c);begin

c := 0end;

Podstawy analizy algorytmów

procedure tick(c);begin

for i := 1 to c do rzuć monetę;if wypadły same orły then return(c+1)

end;

function count(c);begin

return(2c–1)end;

Page 19: W05 - Złożoność pamięciowa

OptymalnośćOptymalność

Istnieje pewna granica, której nie można przekroczyć,poprawiając złożoność algorytmu. Granica ta podyktowana jestwewnętrzną złożonością problemu, tzn. minimalną ilością pracyniezbędnej do wykonania w celu rozwiązania zadania. Aby zbadaćzłożoność obliczeniową problemu, musimy wybrać operacjępodstawową charakterystyczną dla danego problemu i klasy

Podstawy analizy algorytmów

podstawową charakterystyczną dla danego problemu i klasyalgorytmów go rozwiązujących. Następnie odpowiedzieć napytanie, ile takich operacji trzeba wykonać w najgorszymprzypadku. Mówimy, że algorytm jest optymalny, jeśli żadenalgorytmw rozważanej klasie nie wykonuje mniej operacji.

Page 20: W05 - Złożoność pamięciowa

W jaki sposób pokazuje się, że algorytm jest optymalny?Najczęściej dowodzi się, że istnieje pewne dolne oszacowanieliczby operacji podstawowych potrzebnych do rozwiązaniaproblemu. A zatemmusimy wykonać dwa zadania:

1. Zaprojektować możliwie najlepszy algorytm A. Następnieprzeanalizować algorytm A, otrzymując złożoność najgorszego

Podstawy analizy algorytmów

przeanalizować algorytm A, otrzymując złożoność najgorszegoprzypadkuW(n).

2. Dla pewnej funkcjiF udowodnić twierdzenie mówiące, że dladowolnego algorytmu w rozważanej klasie istnieją dane rozmiaruntakie,że algorytmmusi wykonać przynajmniejF(n) kroków.

Jeśli funkcje W i F są równe, to algorytmA jest optymalny. Jeślinie, to być może istnieje lepszy algorytmlub lepsze oszacowaniedolne.

Page 21: W05 - Złożoność pamięciowa

Jeżeli stwierdzamy, iż pewien algorytmma złożoność czasowąW(n), abstrahując od struktury danych, to rozumiemy,że W(n) jestminimalną możliwą liczbą kroków wykonywanych przez tenalgorytm w najgorszymprzypadku danych, gdzie minimumjestrozciągniętenawszystkiemożliwe strukturydanych.

Podstawy analizy algorytmów

rozciągniętenawszystkiemożliwe strukturydanych.

ALGORYTMY + STRUKTURY DANYCH ALGORYTMY + STRUKTURY DANYCH = PROGRAMY= PROGRAMY

Page 22: W05 - Złożoność pamięciowa

KONIECKONIEC