• Nie Znaleziono Wyników

Przyspieszenie algorytmu równoległego CLCS-CUDA w stosunku do algoryt- algoryt-mu sekwencyjnego dla procesora CPU jest

niezmienniczy względem transpozycji

Wniosek 9.10. Przyspieszenie algorytmu równoległego CLCS-CUDA w stosunku do algoryt- algoryt-mu sekwencyjnego dla procesora CPU jest

. (9.25)

Koszt dostępów do pamięci globalnej wyznaczony jest w (9.18), z czego sumaryczna złożoność czasowa algorytmu jest

a więc przyspieszenie wynosi Θ

a więc przyspieszenie jest

Θ(η2). (9.30)

Wyniki (9.28) i (9.30) mogą być zapisane łącznie, co można podsumować następująco:

Wniosek 9.10. Przyspieszenie algorytmu równoległego CLCS-CUDA w stosunku do algoryt-mu sekwencyjnego dla procesora CPU jest

Θ

9.4. Algorytm równoległy dla procesorów graficznych 189 9.4.2. Wyniki eksperymentalne

W celu porównania zaproponowanego algorytmu do algorytmów dla procesorów CPU wy-konane zostały eksperymenty z użyciem takiego samego następującego zestawu komputerowe-go, kompilatora i biblioteki CUDA jak w podrozdz. 7.6.5.

Wszystkie czasy są medianami ze 101 wykonań. Zamiast czasów absolutnych na wykresach pokazane jest przyspieszenie w stosunku do odpowiednich algorytmów sekwencyjnych (działa-jących na jednym rdzeniu procesora CPU). Algorytmy na wykresach oznaczane są następująco:

• CPU-s – algorytm sekwencyjny dla procesorów CPU,

• CPU-p – algorytm równoległy dla procesorów CPU (zastosowany procesor CPU zawiera 4 rdzenie, ale wstępne eksperymenty pokazały, że lepiej jest uruchamiać naraz 32 wątki),

• GPU – algorytm równoległy dla procesorów GPU z tablicą pośredniczącą.

Ponieważ problem CLCS pojawił się w bioinformatyce i dotyczył porównywania łańcuchów białkowych, w eksperymentach, których wyniki pokazane są na rys. 9.20, ustalonoσ= 20. Dla krótkich i średniej długości ciągów ukierunkowujących oraz dla dostatecznie długich ciągów głównych algorytmGPU osiąga przyspieszenie 40–50 w stosunku do ulepszonego algorytmu sekwencyjnego China i in.

Dla krótkich ciągów głównych (n = m = 210) przyspieszenie jest znacznie mniejsze, ponie-waż: (i) pudełka są małych rozmiarów, (ii) liczba pudełek jest mała i nie wszystkie multiproce-sory są obciążone, albo obciążone są w niewielkim stopniu i obciążenie nie jest zbalansowane.

AlgorytmCPU-p jest tylko ok. 2,5 razy szybszy niż CPU-s, głównie z uwagi na duży rozmiar przetwarzanych danych, co prawdopodobnie powoduje większą liczbę chybień w pamięci pod-ręcznej, jeśli naraz wiele wątków przetwarza te dane.

Na rysunkach 9.20c–d pokazana jest zależność przyspieszenia od rozmiaru alfabetu dla cią-gów głównych różnych długości. Dla relatywnie krótkich ciącią-gów głównych (n = m = 211) przy-spieszenie wynosi ok. 12 dla małych alfabetów i maleje do ok. 3 dla alfabetów dużych. Spo-wodowane to jest faktem, że dla dużych alfabetów i krótkich ciągów głównych zastosowanie techniki punktów wejścia-wyjścia powoduje redukcję przetwarzanej macierzy do bardzo ma-łego jej fragmentu. Często już na etapie przetwarzania wstępnego (po wyznaczeniu punktów wejścia-wyjścia) wiadomo, że szukany podciąg nie istnieje. Dla dłuższych ciągów głównych (n = m = 213) przyspieszenie jest znacznie lepsze (bliskie 50) i nie maleje tak szybko, nawet dlaσ= 256. Przyspieszenia algorytmów GPU i CPU-p są na tyle różne, że ewentualny algo-rytm hybrydowy CPU+GPU, który byłoby bardzo trudno zaproponować z uwagi na duże ilości danych przesyłanych do/z pamięci i problemy synchronizacyjne, mógłby być szybszy od algo-rytmuGPU tylko nieznacznie.

10 11 12 13 14 1

2 5 10 20

50 GPU

CPU-s CPU-p

log2n = log2m

Przyspieszenie

10 11 12 13 14

1 2 5 10 20

50 GPU

CPU-s CPU-p

log2n = log2m

Przyspieszenie

a)σ= 20, r = 4 b)σ= 20, r = 16

2 5 10 20 50 100 200

1 2 5 10 20 50

GPU

CPU-s CPU-p

Rozmiar alfabetu

Przyspieszenie

2 5 10 20 50 100 200

1 2 5 10 20

50 GPU

CPU-s CPU-p

Rozmiar alfabetu

Przyspieszenie

c) n = m = 211, r = 12 d) n = m = 213, r = 12

Rys. 9.20. Porównanie przyspieszeń uzyskiwanych przez równoległy algorytm programowa-nia dynamicznego dla procesorów GPU (problemu CLCS). Rozmiary pudełek:

bw= min(max(m/25, 26), 28), bh= min(max(m/26, 25), 26), bcpuh , bcpuw ∈ [28, 29]

Fig. 9.20. Comparison of the speedup for the classical CLCS dynamic programming algorithm. Box sizes: bw= min(max(m/25, 26), 28), bh= min(max(m/26, 25), 26), bcpuh , bcpuw ∈ [28, 29]

9.5. Podsumowanie

Problem najdłuższego ukierunkowanego wspólnego podciągu (CLCS) był rozważany w la-tach 2003–2010 w co najmniej kilkunastu publikacjach. Główne jego zastosowania znajdują się przede wszystkim w bioinformatyce. W niniejszym rozdziale przedstawiono krótko istniejące dla tego problemu algorytmy oraz omówiono nieco dokładniej algorytm China i in. [42], który był punktem wyjścia do części badań autora.

W dalszej części rozdziału zaproponowano kilka algorytmów rozwiązywania tego proble-mu. Historycznie pierwszy był algorytm dedykowany dla niewielkiej liczby dopasowań oparty na metodzie Hunta–Szymanskiego (podrozdz. 9.2) znanej z problemu LCS. Był to pierwszy algorytm, którego złożoność czasowa, jeśli wyrazić ją w zależności od długości ciągu wejścio-wego, była niższa niż iloczyn długości wszystkich trzech ciągów wejściowych. W praktyce ten algorytm okazuje się zwykle kilkakrotnie szybszy od algorytmów znanych wcześniej. Algorytm ten został następnie ulepszony przez zastosowanie techniki punktów wejścia-wyjścia, znanej z literatury dla problemu uliniawiania ukierunkowanego ciągów (CPSA). Kolejną propozycją

9.5. Podsumowanie 191 (podrozdz. 9.3) był pierwszy algorytm równoległości bitowej do problemu CLCS. Eksperymen-ty pokazały, że algorytm ten jest kilkunastokrotnie szybszy od algorytmu China i in. oraz kilka-krotnie szybszy od zaproponowanego algorytmu opartego na metodzie Hunta–Szymanskiego.

W ostatniej części niniejszego rozdziału zaproponowano algorytm równoległy dla proceso-rów graficznych (GPU). Algorytm ten jest zproceso-równolegloną wersją algorytmu China i in., która została przeniesiona na procesory GPU, zgodnie ze schematem przedstawionym w podrozdzia-le 7.6.2. W przeprowadzonych eksperymentach okazało się, że uzyskane przyspieszenie w sto-sunku do algorytmu China i in. wynosiło często ok. 40–50, co jest wynikiem bardzo dobrym i pozwala mieć nadzieję, że przyspieszenie będzie jeszcze większe dla nowszych procesorów graficznych.

Jedną z najważniejszych otwartych kwestii dotyczących problemu CLCS pozostaje pyta-nie, czy możliwe jest skonstruowanie algorytmu o złożoności czasowej o(nmr) (niezależnie od długości ciągu wynikowego). Również w algorytmie równoległości bitowej pojawia się nie-rozwiązany problem, czy możliwe jest uzyskanie przyspieszenia liniowo zależnego od długo-ści słowa komputerowego. Aktualna wersja tego algorytmu cechuje się przyspieszeniem nieco mniejszym.

Z ciekawych prac teoretycznych warto wymienić ostatnio uzyskany wynik [14], dotyczący algorytmu dla problemu CLCS, w którym ciągi wejściowe zostały skompresowane za pomocą algorytmu kodowania długości serii (RLE). Niestety, z uwagi na charakter typowych danych biologicznych taki algorytm nie oferuje znaczącej kompresji. Nie są, jak na razie, znane algo-rytmy dla tego problemu wykorzystujące inne, bardziej zaawansowane metody kompresji, które były stosowane w problemie LCS.

10.1. Wprowadzenie

Problem wyznaczania najdłuższego scalonego wspólnego podciągu (ang. merged longest common subsequence, MerLCS) [116], podobnie do problemu CLCS rozważanego w poprzed-nim rozdziale, był inspirowany badaniami prowadzonymi w bioinformatyce. Danymi wejścio-wymi są tu trzy ciągi: Z, A, B, a oczekiwanym wynikiem jest najdłuższy ciąg S będący podcią-giem Z, który może zostać podzielony na dwa podciągi: S0i S00 takie, że S0jest podciągiem A, a S00 – podciągiem B. Sformułowanie tego problemu wiąże się z faktem, że znajdowanie prze-platających się związków (ang. interleaving relationship) pomiędzy ciągami bywa pomocne dla weryfikacji pewnych hipotez biologicznych. Jedną z nich jest duplikacja całego genomu (ang. whole genome duplication, WGD), po której występuje masowa utrata genów. W [125]

Kellis i in. pokazali, że gatunek Saccharomyces cerevisiae powstał przez duplikację ośmiu ro-dzicielskich chromosomów, po której wystąpiła masowa utrata genów, co jest dowodem na wy-stępowanie WGD w trakcie ewolucji organizmów żywych. Utrata genów wystąpiła w regionach sparowanych, przez co została zachowana przynajmniej jedna kopia każdego genu. Dowód na wystąpienie tego zjawiska opiera się na porównaniu DNA dwóch gatunków drożdży: Saccha-romyces cerevisiae i KluyveSaccha-romyces waltii, które pochodzą od wspólnego przodka, a rozdzieliły się w trakcie ewolucji przed wystąpieniem WGD. Oba te gatunki są związane relacją mapowa-nia 1:2, spełmapowa-niającą kilka kryteriów (szczegóły w [125]), m.in., każdy z siostrzanych regionów w genomie S. cerevisiae zawiera uporządkowany podciąg genów w odpowiadającym mu regio-nie genomu K. waltii. Ponadto, oba siostrzane podciągi odpowiednio scalone zawierają prawie wszystkie geny K. waltii. Rozwiązując problem MerLCS dla tych trzech ciągów (dwa regiony w genomie jednego gatunku i jeden region w genomie drugiego, bliskiego gatunku), można sprawdzić, czy po rozdzieleniu się tych gatunków miała miejsce WGD.

Peng i in. [173] pokazują także możliwe zastosowania problemu MerLCS w innych dzie-dzinach, np. przy porównywaniu sygnałów, kiedy do dyspozycji są trzy ciągi: jeden kompletny i dwa zniekształcone (zaszumione, niekompletne itp.) i należy zweryfikować, czy zniekształco-ne ciągi mogły powstać przez zniekształcenie ciągu kompletzniekształco-nego.

W problemie MerLCS danymi wejściowymi są ciągi: Z = z1z2. . . zr, A = a1a2. . . an, B = b1b2. . . bm, składające się z symboli alfabetu Σ∈ Z. Podobnie jak w innych rozdziałach tej części, bez utraty ogólności można założyć, że m ≤ n.

Problem 10.1 (Najdłuższy scalony wspólny podciąg, MerLCS). Dla ciągów Z, A, B znaleźć taki ciąg S= s1s2. . . s`, o maksymalnej długości, będący podciągiem Z, którego podciąg S0=

10.1. Wprowadzenie 193 si1si2. . . sik, gdzie 1≤ i1< i2< ··· < ik≤ ` jest podciągiem ciągu A, a ciąg S00 otrzymany z S przez usunięcie symboli z pozycji i1, i2, . . ., ikjest podciągiem ciągu B.

Powyższa definicja oznacza, że podciąg MerLCS dla Z, A, B jest najdłuższym wspólnym podciągiem Z oraz dowolnego ciągu, który można otrzymać scalając ciągi A i B.

Przykład 10.1 (Najdłuższy scalony wspólny podciąg, MerLCS). Dla ciągów Z = ABAD, A = DDA oraz B= BAC najdłuższym ukierunkowanym wspólnym podciągiem jest m.in. S = ABA.

W ciągach Z, A, B podkreślono symbole tworzące podciąg MerLCS.

W niniejszym rozdziale używane są takie same operacje bitowe, jakie były stosowane w po-przednich rozdziałach. Ponadto, dla dowolnego wektora bitowego W przez W[i, j] będzie ozna-czany ciąg bitów z W rozpoczynający się na pozycji i-tej, a kończący na pozycji j-tej, a przez W[i] – i-ty bit wektora bitowego W . Notacja ta będzie stosowana do specyfikowania pojedyn-czego (lub jego części) słowa komputerowego w tablicy emulującej długi wektor bitowy.

W literaturze znane są dwa algorytmy rozwiązywania problemu MerLCS. Algorytm Huan-ga i in. [116] opiera się na metodzie programowania dynamicznego i charakteryzuje się złożo-nością czasowąΘ(nmr). Wymaga on, w zależności od implementacji,Θ(nmr) lubΘ(nm) słów pamięci. W [116] dyskutowany jest także problem, będący uogólnieniem problemu MerLCS.

Nakłada się w nim pewne dodatkowe ograniczenia na to, jak można scalać ciągi A i B. Problem ten (Block-MerLCS) nie będzie jednak przedmiotem rozważań w niniejszym rozdziale. Algo-rytm Huanga i in. dla problemu MerLCS sprowadza się do następującej formuły rekurencyjnej:

M(i, j, k) = max

















M(i − 1, j − 1,k) + 1, jeśli zi= aj, M(i − 1, j,k − 1) + 1, jeśli zi= bk,

max







M(i − 1, j,k), M(i, j − 1,k), M(i, j, k − 1),

jeśli (zi6= aj) ∧ (zi6= bk),

(10.1)

z warunkami brzegowymi określonymi następująco:

M(0, j, k) = 0, M(i, 0, 0) = 0,

M(i, j, 0) = LLCS(Zi, Aj), M(i, 0, k) = LLCS(Zi, Bk),

(10.2)

dla wszystkich poprawnych wartości i, j, k. Przez LLCS oznaczana jest długość podciągu LCS.

Po zakończeniu obliczeń w M(r, n, m) znajduje się długość ciągu wynikowego, a sam ciąg moż-na uzyskać odpowiednio przechodząc macierz M począwszy od M(r, n, m).

(a)

Rys. 10.1. Przykład obliczeń dla problemu MerLCS i ciągów Z = ABA, A = DDA, B = BAC wyko-nywanych zgodnie z (a) zależnością oryginalną (10.1), (b) zależnością poprawioną (10.3).

Wyszarzone komórki oznaczają dopasowania

Fig. 10.1. Example of computation of the MerLCS for Z = ABA, A = DDA, B = BAC according to (a) original formula (10.1), (b) fixed formula (10.3). Gray cells denote matches

Równanie (10.1) zawiera jednak pewien błąd, co można zaobserwować na rys. 10.1a, gdzie znajduje się przykład macierzy uzyskanej według tej zależności. Według algorytmu Penga i in.

wynikiem jest podciąg długości 2, ponieważ M(3, 3, 3) = 2, podczas gdy poprawnym wynikiem jest podciąg długości 3, gdyżABA jest podciągiem Z = ABA, który może zostać rozdzielony naA (podciąg A = DDA) oraz BA (podciąg B = BAC). Na szczęście błąd ten łatwo skorygować otrzymując zależność:

Warunki brzegowe pozostają bez zmian.

Lemat 10.1. Zależność (10.3) z warunkami brzegowymi (10.2) poprawnie wyznacza podciąg