- Algorytmy jednordzeniowe
- Algorytm przestrzeni liniowej L S_D L
- Wydajny algorytm liniowo-przestrzenny S t r i p_D L
- Algorytm L S D L_T R A C E
- Algorytm strip trace S t r i p_T R A C E
- Algorytmy wielordzeniowe
- Algorytm P P_D L
- Algorytm P P_L S_D L
- Algorytm P P_S t r i p_D L
- Algorytm P P_D L_T R A C E
- Algorytmy P P_L S D L_T R A C E i P P_S t r i p_T R A C E
Algorytmy jednordzeniowe
W tym rozdziale rozwijamy cztery liniowo-przestrzenne, jednordzeniowe algorytmy korekcji ciągów za pomocą odległości DL. Wszystkie cztery działają w czasie O(mn). Pierwsze dwa (LS_DL i Strip_DL) obliczają jedynie wynik Hmn optymalnego śladu; różnią się one wydajnością pamięci podręcznej. Ostatnie dwa (LSDL_TRACE i Strip_TRACE) obliczają optymalny ślad.
Algorytm przestrzeni liniowej L S_D L
Pozwólmy s być rozmiarem alfabetu. Zamiast tablicy H używanej w DL, algorytm LS_DL używa jednowymiarowej tablicy U i dwuwymiarowej tablicy T. Te dwie tablice mają wymaganą przestrzeń O((s+1)n) = O(n) dla stałego s. Gdy m<n, można zamienić A i B, aby zmniejszyć wymaganą pamięć. Dodając pamięć potrzebną dla A i B, złożoność przestrzenna wynosi O(s min{m,n}+m+n) = O(m+n) gdy s jest stałe.
Podobnie jak w algorytmie DL, wartości Hij są obliczane przez wiersze. Jednowymiarowa tablica U jest używana do zapisywania wartości H obliczonych przez algorytm DL, gdy obliczany jest wiersz i. Niech H będzie ostatnim rzędem obliczonym dla znaku c. Wtedy T jest rzędem w-1 H. Algorytm 2 podaje pseudokod LS_DL. Jego poprawność wynika z poprawności algorytmu DL. Zauważ, że swap(T],U) zajmuje O(1) czasu, gdyż zamieniane są wskaźniki do 2 tablic jednowymiarowych, a nie zawartość tych tablic. Liczba pominięć pamięci podręcznej dla LS_DL jest taka sama jak dla DL, gdy n jest odpowiednio duże, ponieważ oba mają ten sam wzorzec dostępu do danych. Jednakże, dla mniejszych instancji LS_DL będzie wykazywał znacznie lepsze zachowanie pamięci podręcznej. Na przykład, ze względu na wykorzystanie znacznie mniejszej ilości pamięci, możemy mieć wystarczająco dużo pamięci podręcznej LLC, aby przechowywać wszystkie dane w LS_DL, ale nie w DL (O(sn) vs O(mn)).
Wydajny algorytm liniowo-przestrzenny S t r i p_D L
Gdy (s+1)n jest większe niż rozmiar pamięci podręcznej LLC, możemy zredukować liczbę chybień pamięci podręcznej względem algorytmu LS_DL, obliczając Hij za pomocą pasków o szerokości q, dla jakiegoś q mniejszego niż n (ostatni pasek może mieć szerokość mniejszą niż q). Jest to pokazane na Rys. 3. Paski są obliczane w kolejności 0, 1,… za pomocą algorytmu LS_DL. Jednak przestrzeń potrzebna przez T i U w LS_DL jest zredukowana do (s+1)q, ponieważ szerokość pasków wynosi q, a nie n. Wybierając q wystarczająco małe, możemy zapewnić, że bloki tablic T i U używane przez LS_DL nie są eksmitowane z pamięci podręcznej po ich wprowadzeniu. Tak więc, jeśli każdy wpis T i U zajmuje 1 słowo, to gdy rozmiar pamięci podręcznej wynosi lw, mamy q<lw/(s+1). Zauważmy, że oprócz T i U, cache musi pomieścić partiale A, B i inne tablice potrzebne do przekazania danych z jednego paska do następnego.
Aby przekazać dane z jednego paska do następnego, używamy dodatkowego jednowymiarowego paska tablicowego o rozmiarze m oraz dwuwymiarowej s∗m tablicy V. Pasek tablicy zapisuje wartości H obliczone dla najbardziej prawej kolumny w pasku. V podaje wartość H w najbardziej na prawo wysuniętej kolumnie j w wierszu i tablicy H, która (a) znajduje się w pasku na lewo od aktualnie obliczanej i (b) c=B.
Pseudokod dla Strip_DL jest podany w algorytmie 3. Dla jasności, pseudokod ten wykorzystuje dwie tablice strip (linie 18 i 30) oraz dwie tablice V (linie 24 i 32). Jeden zestaw tablic jest używany do pobierania danych obliczonych dla poprzedniego paska, a drugi do danych, które mają być przekazane do następnego paska. W rzeczywistej implementacji używamy pojedynczej tablicy pasków i pojedynczej tablicy V nadpisującej wartości otrzymane z poprzedniego paska wartościami, które mają być przekazane do następnego paska.
Czas i złożoność Strip_DL wynoszą odpowiednio O(mn) i O((s+1)m+(s+1)q+n) = O(sm+sq+n) = O(sm+n), ponieważ q jest stałą. Gdy m>n, możemy przełączać A i B, aby zachować pamięć, a więc złożoność przestrzeni staje się O(s min{m,n}+m+n) = O(m+n) dla stałej s.
Gdy analizujemy miss pamięci podręcznej, zauważamy, że q jest wybrane tak, że U i T mieszczą się w pamięci podręcznej. Przyjmujemy rozsądne założenie, że reguła wymiany LRU nie powoduje, że żaden blok U lub T nie jest eksmitowany podczas działania algorytmu Strip_DL. W rezultacie, całkowita liczba pominięć pamięci podręcznej spowodowanych przez U i T jest niezależna od m i n, a więc może być pominięta w analizie. Inicjalizacja paska i V powoduje odpowiednio m/w i (s+1)m/w dostępów do odczytu. Liczba dostępów do zapisu jest w przybliżeniu taka sama jak liczba dostępów do odczytu. Obliczenia dla każdego paska uzyskują dostęp do paska tablicy w kolejności rosnącej według indeksu. Powoduje to (w przybliżeniu) taką samą liczbę pominięć pamięci podręcznej, jak podczas fazy inicjalizacji. W związku z tym, całkowita liczba pominięć pamięci podręcznej spowodowanych paskami wynosi w przybliżeniu (2m/w)(n/q+1). Dla V, zauważamy, że podczas obliczania bieżącego stripu, elementy w dowolnym wierszu V są dostępne w kolejności nie malejącego indeksu (tj. od lewej do prawej) oraz że musimy zachować w pamięci podręcznej tylko ostatnio odczytaną wartość dla każdego znaku alfabetu (tj. zachowanych ma być co najwyżej s wartości). Przyjmując założenie, że wartość V jest usuwana z pamięci podręcznej tylko wtedy, gdy uzyskiwany jest dostęp do nowej wartości dla tego samego znaku, całkowita liczba pominięć odczytu z V podczas obliczania pojedynczego paska wynosi sm/w. Liczba braków zapisu jest w przybliżeniu taka sama. Zatem, V przyczynia się do (2sm/w)(n/q+1). Stąd całkowita liczba chybień pamięci podręcznej dla algorytmu Strip_DL wynosi ≈2(s+1)mn/(wq), gdy m i n są duże.
Przypomnijmy, że przybliżona liczba chybień pamięci podręcznej dla algorytmów DL i LS_DL wynosi mn(1+3/w). Jest to (wq+3q)/(2s+2) razy więcej niż dla Strip_DL.
Algorytm L S D L_T R A C E
Ale algorytmy LS_DL i Strip_DL wyznaczają wynik (koszt) optymalnego śladu (a więc optymalnej sekwencji edycji), który przekształca A w B, algorytmy te nie zachowują wystarczającej ilości informacji, aby faktycznie wyznaczyć optymalny ślad. Aby wyznaczyć optymalny ślad używając przestrzeni liniowej, przyjmujemy strategię „dziel i zwyciężaj” podobną do tej używanej przez Hirschberga dla prostego problemu edycji łańcuchów (tzn, transpozycje nie są dozwolone) oraz Myersa i Millera dla problemu wyrównywania sekwencji.
Mówimy, że ślad ma środkowe przejście, jeśli zawiera dwie linie (u1,v1) i (u2,v2), u1<u2 takie, że v1>n/2 i v2≤n/2 (Rys. 4).