• Nie Znaleziono Wyników

Algorytm równoległości bitowej

WSPÓLNE PODCIĄGI

7. Najdłuższy wspólny podciąg

7.3. Algorytmy sekwencyjne i równoległości bitowej

7.3.4. Algorytm równoległości bitowej

Jednym z wydajniejszych podejść w projektowaniu szybkich algorytmów w dziedzinie prze-twarzania tekstów i ciągów jest użycie równoległości bitowej. Autorem tego podejścia jest Dömölki [76], jednak później było one odkrywane wielokrotnie, a największy wpływ na współ-czesne prace miały artykuł Baeza-Yatesa i Gonneta [26] oraz wcześniejsza rozprawa doktorska Baeza-Yatesa [25]. Podstawowa koncepcja tego podejścia opiera się na dwóch prostych obser-wacjach. Po pierwsze, do przechowywania wyniku niektórych obliczeń wystarczy jeden bit.

Przykładem może tu być porównywanie liter w problemie wyszukiwania wystąpienia wzorca w tekście, gdzie wynikiem jest prawda lub fałsz. Po drugie, niektóre obliczenia mogą być wy-konywane równolegle na wielu bitach. Ponieważ dzisiejsze komputery dysponują procesorami o długości słowa komputerowego wynoszącej 32 lub 64 bity, więc potencjalne przyspieszenie jest duże. Oczywiście, nie zawsze podejście to może być zastosowane, gdyż jeden bit w

wie-7.3. Algorytmy sekwencyjne i równoległości bitowej 99 LCS-BP-Length(A, B)

Wejście: A, B – ciągi, dla których wyznaczana jest długość podciągu LCS Wyjście: znaleziona długość podciągu LCS

{Przetwarzanie wstępne}

1 for x ∈Σdo Yx← 0m

2 for j ← 1 to m do Ybj ← Ybj| 0m− j10j {Obliczenia właściwe}

3 V ← 1m

4 for i ← 1 to n do 5 U← V & Yai

6 V ← (V +U) | (V −U)

{Wyznaczanie liczby bitów o wartości 0 w V – długości podciągu LCS}

7 ` ← 0; V ← ∼V 8 while V 6= 0mdo

9 ` ← ` + 1; V ← V & (V − 1) 10 return `

Rys. 7.6. Bitowo-równoległy algorytm Hyyrö wyznaczający długość podciągu LCS [120]

Fig. 7.6. Bit-parallel algorithm computing the LCS length by Hyyrö [120]

lu przypadkach nie wystarcza do reprezentacji wyniku obliczeń, a także często niemożliwe jest wykonywanie równoległych obliczeń na wielu bitach tego samego słowa komputerowe-go. W związku z tym zwykle opracowanie algorytmu równoległości bitowej dla konkretnego problemu nie należy do zadań łatwych. Jako zgrubną regułę można przyjąć, że najlepszymi kan-dydatami spośród klasycznych algorytmów do przekształcenia ich w algorytmy równoległości bitowej są algorytmy najprostsze. Przykładowo, algorytm równoległości bitowej Shift-Or [106]

wyszukujący wystąpienia wzorca w tekście jest odmianą algorytmu naiwnego wyszukiwania wzorca.

Analizując macierz programowania dynamicznego dla problemu LCS (rys. 7.2), można za-obserwować, że różnice pomiędzy sąsiednimi komórkami wynoszą 0 lub 1. Obserwacja ta, któ-rej dowód można znaleźć m.in. w [120], jest bardzo pomocna w konstrukcji algorytmu opartego na równoległości bitowej (BP), ponieważ alternatywnym sposobem reprezentacji tej macierzy jest przechowywanie w poszczególnych komórkach tylko bitowej informacji, czy wartość w da-nej komórce jest równa wartości z komórki znajdującej się powyżej, czy jest od niej większa.

Co więcej, można pokazać, że przy takiej reprezentacji wartości w poszczególnych wierszach można obliczać równolegle. Istnieją przynajmniej trzy algorytmy równoległości bitowej dla problemu LCS zaproponowane przez Allison i Dix [8], Crochemore’a i in. [52], Hyyrö [120].

Ostatni z tych algorytmów (rys. 7.6) jest zwykle w praktyce najszybszy, dlatego poniżej właśnie on zostanie przedstawiony. Pozostałe algorytmy są do niego podobne, a dyskusję różnic można znaleźć w [120].

Rysunek 7.7 ilustruje wyznaczanie długości podciągu LCS za pomocą tego algorytmu. Ma-cierz programowania dynamicznego przedstawiona w prawej części rysunku została pokazana

0

Rys. 7.7. Przykład działania bitowo-równoległego algorytmu Hyyrö dla problemu LCS Fig. 7.7. An example of the bit-parallel algorithm by Hyyrö for the LCS problem

tylko dla zilustrowania wykonywanych operacji i nie jest ona wprost obliczana w algorytmie LCS-BP-Length. Algorytm działa na wektorach bitowych. Dla prostoty opisu założone zosta-nie na razie, że każdy z wektorów bitowych mieści się w pojedynczym słowie komputerowym.

RamkaMaski zawieraσwektorów bitowych, po jednym na każdy symbol alfabetu. Wektory te obliczane są w etapie przetwarzania wstępnego (wiersze1–2 algorytmu). Bit o indeksie j wek-tora związanego z symbolem x ∈Σma wartość1 wtedy i tylko wtedy, gdy bj= x. Głównym wektorem, na którym prowadzone są obliczenia, jest V . Odzwierciedla on różnice w warto-ściach poszczególnych komórek w kolumnie macierzy programowania dynamicznego, tj. j-ty bit V ma wartość0 wtedy i tylko wtedy, gdy M(i, j) − M(i, j − 1) = 1, dla aktualnej i-tej ko-lumny. Alternatywnie można stwierdzić, że indeks j bitu o wartości 0 w V po przetworzeniu i-tej kolumny jest najmniejszym indeksem wiersza takim, że (i0, j) jest dopasowaniem pewnej rangi h i i0≤ i. Kolejne ramki rysunku (i = 0, i = 1, . . . , i = 4, i = 12) przedstawiają zawar-tość wektora V po przetworzeniu i-tej kolumny. Dla i = 1 przedstawionych jest nieco więcej szczegółów, które ilustrują obliczenia wykonywane w wierszach5–6 algorytmu. Bity o warto-ściach0 w wektorze V i komórki macierzy M, których wartość jest większa niż wartość górnego sąsiada, zostały wyczernione na rysunku, aby podkreślić związek pomiędzy kolumnami macie-rzy M i wektorem V . W wierszach7–9 wyznaczana jest liczba bitów o wartości 0 w ostatnim wektorze V , która jest długością podciągu LCS.

W przypadku gdy m > w, konieczne jest reprezentowanie wektorów bitowych jako tablic słów komputerowych. Nie stanowi to jednak większego problemu, gdyż wszystkie potrzeb-ne operacje bitowe można wykonywać na poszczególnych słowach niezależnie. Podobnie przy odejmowaniu wektorów bitowych nie może w tym algorytmie powstać przeniesienie. Jedynie przy dodawaniu powstaje konieczność obsługi przeniesienia, ale jest to proste do zrealizowania.

Główna pętla algorytmu wykonywana jest n razy a w każdym jej przebiegu ma miejsce tyl-ko kilka operacji bitowych i arytmetycznych. Z uwagi na to, że wektory bitowe emulowane są

7.3. Algorytmy sekwencyjne i równoległości bitowej 101 przez tablice słów komputerowych o rozmiarach dm/we słów, złożoność czasowa przedstawia-nego algorytmu jestΘ(ndm/we). Złożoność pamięciowa tego algorytmu jestΘ(dm/we) słów na wektor V oraz Θ(σdm/we) słów na wektory masek. Do tego należy jeszcze doliczyć roz-miar danych wejściowych, co sumarycznie dajeΘ(n +σdm/we). W przypadku gdy nie można założyć, żeσ= O(n), możliwe jest (podobnie jak dla algorytmu Hunta–Szymanskiego) prze-chowywanie wektorów masek w drzewie poszukiwań binarnych. Daje to złożoność pamięciową Θ(ndm/we) słów przy złożoności czasowejΘ(ndm/we + nlogn).

W celu wyznaczenia podciągu LCS długości ` konieczne jest wykonanie przejścia po wy-generowanej macierzy bitowej algorytmem LCS-BP-Sequence (rys. 7.8).3 W tym przypadku należy też tak zmodyfikować algorytm LCS-BP-Length, aby zapisywał zawartość wektoraV po przetworzeniu każdej kolumny. Niech zatem V (i) zawiera tę wartość dla i-tej kolumny. Warto-ści bitów znajdujących się w V (i) będą służyły jako swego rodzaju „drogowskazy” wskazujące, w którym kierunku należy przesuwać się po macierzy bitowej. Jeśli j-ty bit wektora V (i) za-wiera1, to oznacza to, że M(i, j) = M(i, j −1), a więc możliwe jest przejście z komórki (i, j) do (i, j − 1), ponieważ rangi obu tych par są takie same. W przeciwnym przypadku przejście na-stępuje do komórki (i −1, j), ponieważ ranga tej pary jest nie mniejsza niż ranga pary (i, j −1).

Oczywiście, jeśli (i, j) jest dopasowaniem, to przejście odbywa się do (i − 1, j − 1), a sym-bol ai dołączany jest do ciągu wynikowego. Złożoność czasowa tego algorytmu konstrukcji wyniku na podstawie znanych wektorów bitowych V jestΘ(m + n) =Θ(n), ponieważ w każ-dym przebiegu pętli zmniejszana jest wartość co najmniej jednego z pary indeksów i, j, których początkowe wartości wynoszą odpowiednio n, m. Złożoność pamięciowa tego algorytmu jest Θ(ndm/we) słów niezależnie od tego czyσ= O(n), czy też nie.