Изменения

Поиск повторов в ДНК на основе ОСАМ

18 829 байтов добавлено, 20:57, 24 марта 2010
м
Нет описания правки
Или '''Применение «Применение обобщенного спектрально-аналитического метода в задаче анализа биологических данных — План презентацииданных»'''.
Ключевая задача анализа геномных последовательностей: поиск повторов. Прямых, обратных, симметричных. Что есть геномная последовательность? По сути, длинная строка в алфавите A, T, G, C (аденин, тимин, гуанин, цитозин — привет, биология за 10-й класс). T и C близки, это «[[rupedia:Пиримидин|пиримидиновые]] основания». G и A тоже близки, это «[[rupedia:Пурин|пуриновые]] основания». Методов куча, но есть '''Проблема: Последовательности Очень Длинные''', анализ долгий. Если искать точные повторы, ещё более-менее, но как только переходим к поиску неточных повторов, сразу всё сильно замедляется. По поводу «обычных» методов — например, можно посмотреть программу UniPro DPView — творение неких Новосибирских коллег. Ещё и адовые проекты [http://www.bioperl.org/ BioPerl], [http://www.biopython.org/ BioPython] — большие сборники различных методов и библиотек решения биологических задач — в частности, и методов поиска повторов.
# Ключевая задача анализа геномных последовательностей: поиск повторов. Прямых, обратных, симметричных. Что есть геномная последовательность? По сути, длинная строка в алфавите A, T, G, C (аденин, тимин, гуанин, цитозин, привет, биология, 10-й класс). T и C близки, это «пиримидины». G и A тоже близки, это «пурины». Методов куча, но есть и Проблема: последовательности очень длинные, анализ долгий. Если искать точные повторы, ещё более-менее, но как только переходим к поиску неточных повторов, всё сразу сильно замедляется. По поводу «обычных» методов — например, можно посмотреть программу UniPro DPView — творение неких Новосибирских коллег. Ещё есть довольно адские проекты BioPerl, BioPython — большие сборники всяких методов и библиотек по поводу биологических задач, в частности, и методов поиска повторов, на скриптовых языках.# '''ОСАМ. ''' Мысль простаяпроста: разложить сигнал по какому-нибудь классическому ортогональному базису, получить краткое описание, к тому же обладающее различными приятными свойствами. Обработать на основе описания сигнала. Применять можно в широком спектре задач распознавания. Свойства описания - «более важная» информация в первых коэффициентах(норма сохраняется; отсекая хвост, можно получать получаем приближения сигнала; норма сохраняется; для неточных разложений есть мера точности разложения; и т.&nbsp;п. Т.&nbsp;е. есть хороший, проработанный, мат. аппарат.# Идея: применить ОСАМ к поиску повторов в ДНК, таким образом ускорив его. Как?! Во-первых, <nowiki>построить профиль последовательности, т.&nbsp;е. перевести её в длинный числовой вектор, выбрав w — окно профиля, и принимая за каждый элемент последовательности (количество пуринов в w-окрестности элемента) минус (количество пиримидинов в w-окрестности элемента). Далее, выбирая по N значений из полученной последовательности — 0..N-1, s..N+s-1, 2s..N+2s-1, … (s — шаг аппроксимации) и раскладывая получаемые вектора из N чисел по k коэффициентам некоторого базиса, получить «индекс» последовательности. k << N, потому и «индекс». Далее пробежаться по всем полученным описаниям (по индексу) обеих последовательностей (или одной и той же последовательности) и сравнить попарно все пары описаний (на похожесть). А что такое похожесть? Критериев похожести можно выработать массу, среди них можно найти устойчивые к масштабу и т.&nbsp;п., однако у нас всё довольно просто:</nowiki><math>\frac{|a-b|}{|a|+|b|}</math>, где <math>|x|=\sqrt{\sum {x}_{i}^{2}}</math>. Такое вот «нормированное L<sub>2</sub>-расстояние». Здесь, кстати, можно выиграть от т.&nbsp;н. «принципа дискриминантности», который гласит очевидную вещь: что если <math>\frac{\sqrt{{\sum }_{i=0}^{k}{({a}_{i}-{b}_{i})}^{2}}}{|a|+|b|}> \mathrm{eps}</math><nowiki>уже при k < n, то суммирование можно обработать не продолжать, т.&nbsp;к. меньше сумма квадратов уже не станет. Итак, что мы получим от этого сравнения? Мы получим приближённые «близости» участков ДНК. Крупных или мелких, более или менее точное сравнение — это уже как захотим — для этого можно варьировать параметры. Задаём порог, можем пробежаться по результатам и сразу выявить «подозрительные на повторы» участки. Это есть важно, т.&nbsp;к. больше не нужно всё время искать повторы ВЕЗДЕ: сначала достаточно выявить крупные относительно похожие участкисигнал, а потом можно «увеличить масштаб» и выявить (или не выявить) точные координаты повторовописание. Кстати, единственное, для чего подход почти не подходит - для выявления «абсолютно точных» координат повторов. Это уже Применим в «подозрительных» областях можно делать стандартными методами. Например, diffоподобным алгоритмом. :-)</nowiki># Кстати, нужно использовать все современные возможности процессоров. Иначе будет обидно, если такую же программу написать на MATLAB'е и она - опа! - окажется быстрее в 5 раз. То есть нужно не забывать о многопоточности, не забывать об SIMD инструкциях, не забывать об аппаратном ускорении математических функций. Засчёт этого всего выигрываем в скорости ещё больше, реальная разница — в 10-20 раз (Core 2 Duo). Как?! Для многопоточности - голые нити (треды), никаких OpenMP! Т.к. это костылистая штуковина, приводит либо к сильному ухудшению структуры кода (причём фактическая логика получается аналогична голым тредам), либо к большим накладным расходам на распараллеливание — 5-15%. Так что треды. Плюс библиотека Intel Integrated Performance Primitives для SIMD и аппаратного ускорения инструкций. А что это - IPP? А это такой векторный ассемблер, только на C. Библиотека, содержащая в себе оптимальные реализации большого спектра векторных операций (есть почти всё, что душе угодно — от сложений, умножений, корней и синусов, до узкоспециализированных функций ускорения декодирования аудио и видео, широком спектре задач распознавания речи и т.д и т.п) для процессоров, имеющих различные расширения типа MMX / SSE1/2/3/4/5/+. Выражения над векторами там писать, к несчастью, нельзя, потому и получается код типа:#:ippsCopy_64f(xn, wn, n);#:ippsSqr_64f_I(wn, n);#:ippsAddC_64f_I(-1, wn, n);#:ippsMulC_64f(wn, -1, tn, n);#:ippsSqrt_64f_I(tn, n);# Вот где-то примерно это всё и было реализовано. Есть относительно простая программа, есть относительно хорошая библиотека для абстрагирования от деталей реализации конкретных базисов, есть сами базисы — Чебышева 1 и 2 рода, Якоби, Лежандра, Лагерра, Эрмита, Фурье, ДКП, ДСП. Она работает и рисует красивые картинки. [показать пару картинок и закончить]. Кстати, по поводу того, а какой же базис лучше? Вообще они все дают очень похожие результаты... Пока что «лучше» всех Чебышев 1-го рода. А что вообще такое «лучше»? «Лучше» - чисто умозрительно это «больше соотношение сигнал/шум» (в результатах). Как измерить? Ну, например, при одинаковых параметрах окон и глубине разложения подобрать eps такое, чтобы общее количество «похожих» участков было примерно равно, и посчитать, например, среднюю длину повторов. Можно и медиану тоже. Чем больше, тем лучше - мы ведь хотим найти как можно более длинные повторы. Начинали реализовывать с Чебышева 1-го рода, потом пробовали Лежандра, потом думали, что Чебышев 2-го рода произведёт революцию и всё будет гораздо лучше, т.к весовая функция выпуклая, центр отрезка учитывается сильнее, края меньше. Революции не произошло, результаты сильно похожие на 1-го рода, местами получше, местами похуже. Формально — похуже. Дальше есть табличка с «попугаями» по разным базисам. Тестовые данные — часть генома мыши (не спрашивайте какая, я не знаю) длиной 1.5 млн нуклеотидов. Сравнение приводилось при примерно одинаковых количествах найденных участков, «подозрительных» на повтор — в районе 5000. При выбранных настройках минимальная длина участка, подозрительного на повтор — 3500 нуклеотидов. Какие выводы? Лидирует Чебышев 1 рода. Базисы ДКП, ДСП и Фурье дают до жути похожие на него, практически идентичные, результаты. С небольшим отставанием за ними следует Лежандр, за ним — Чебышев 2 рода, а базисы Эрмита и Лагерра не подходят для поиска повторов ''вообще — ''что есть логичный факт, т.&nbsp;к. они оба работают на бесконечном интервале либо (0, +бесконечность), либо от - до + бесконечности. Вариантов значения медианной длины было всего 2: 3500 (минимально возможная) или 10000, она отражает, фактически, чистое количество шума — мелких отрезков, и гласит, что приемлемый уровень шума дают... Ясно кто.
{| style="border-spacing:0;"| style="border-top:0Идея — применить ОСАМ к поиску повторов в ДНК, таким образом ускорив его.002cm solid #000000;borderКак?! Во-bottom:0первых, построить профиль последовательности, т.002cm solid #000000&nbsp;border-left:0е.002cm solid #000000;borderперевести её в длинный числовой вектор, выбрав w — окно профиля, и принимая за каждый элемент последовательности ''(количество пуринов в w-right:none;padding:0окрестности элемента) минус (количество пиримидинов в w-окрестности элемента)''.097cm;"| | style="border-top:Далее, выбирая по N значений из полученной последовательности — <m>(0.002cm solid #000000;border\ldots N-bottom:01), (s \ldots N+s-1), (2s \ldots N+2s-1), \ldots</m> (s — шаг аппроксимации) и раскладывая получаемые вектора из N чисел по k коэффициентам некоторого базиса, получить «индекс» последовательности. k << N, потому «индекс». Далее пробежаться по индексам обеих последовательностей (или одной и той же последовательности) и сравнить попарно все пары описаний на похожесть. А что такое похожесть? Критериев похожести можно выработать массу, среди них можно найти устойчивые к масштабу и т.002cm solid #000000&nbsp;border-left:0п.002cm solid #000000;border-right, однако у нас всё довольно просто:none;padding:0.097cm;"<m>\frac{| Epsa-b|}{|a|+|b|}</m>, где <m>|x| style="border\sqrt{\sum {x}_{i}^{2}}</m>. Типа «нормированного L<sub>2</sub>-top:0расстояния».002cm solid #000000Здесь можно выиграть от т.&nbsp;border-bottom:0н.002cm solid #000000;border-left«принципа дискриминантности», который гласит очевидную вещь:если <m>\frac{\sqrt{{\sum }_{i=0.002cm solid #000000;border}^{k}{({a}_{i}-right:none;padding:0.097cm;"{b}_{i})}^{2}}}{| Среднееa| style="border:0+|b|}> \varepsilon</m> уже при k < n, суммирование можно не продолжать, т.002cm solid #000000&nbsp;padding:0к. ''меньше'' сумма квадратов уже не станет.097cm;"| Медиана
|-| style="border-top:none;border-bottom:0Итак, от этого сравнения мы получим оценку «подобия» участков ДНК.002cm solid #000000;border-left:0Крупных или мелких, более или менее точное сравнение — это уже как захотим — для этого можно варьировать параметры.002cm solid #000000;border-right:none;padding:0.097cm;"| Чебышева 1 рода| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| .025| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0Задаём порог, можем пробежаться по результатам и сразу выявить участки, «подозрительные на повторы».097cm;"| То есть больше не нужно всё время искать повторы «''везде'3978'''| style="border-top:none;border-bottom»:0сначала достаточно выявить крупные относительно похожие участки, а потом можно «увеличить масштаб» и выявить (или не выявить) точные координаты повторов.002cm solid #000000;border-left:0Единственное, для чего подход почти не подходит — для выявления «абсолютно точных» координат повторов.002cm solid #000000;border-right:0Это уже в «подозрительных» областях можно делать стандартными методами.002cm solid #000000;padding:0Например, diff'оподобными алгоритмами.097cm;"| '''10000'''
|-| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| Чебышева 2 рода| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| .0285| styleЧасть статьи ="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| 3882| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:0.002cm solid #000000;padding:0.097cm;"| 3500
|-| style="border-top:none;border-bottom:0Для реализации программы поиска повторов с помощью ОСАМ был выбран язык C++.002cm solid #000000;borderТакой выбор обусловлен сущностью процесса разложения функций, позволяющей с помощью объектно-left:0ориентированного подхода разделить функционал на общий и зависящий от конкретного ортогонального базиса.002cm solid #000000;border-right:none;padding:0.097cm;"| ДКП| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| .025| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| '''3978'''| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0Общий функционал — это функции подсчёта весовых коэффициентов, подсчёта интеграла на сетке Гаусса, подсчёта матрицы Грама заданного базиса, нормирования заданного базиса, интерполяции сигнала на заданную сетку, и воссоздания изначального сигнала по коэффициентам разложения.002cm solid #000000;borderК базисо-right:0зависимому функционалу относятся функции подсчёта сетки, весовых коэффициентов, и самих значений функции.002cm solid #000000;padding:0Также такой подход, кроме всего прочего, даёт возможность оптимизировать части функционала отдельно друг от друга.097cm;"| '''10000'''
|-| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| ДСП| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| .021| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| 3975| style«Наивный» алгоритм ==="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:0.002cm solid #000000;padding:0.097cm;"| '''10000'''
|-| style="border-top:none;border-bottom:0В целом основная задача программного обеспечения поиска повторов на основе ОСАМ — построение спектральной матрицы гомологии последовательности, в общем случае — двух последовательностей.002cm solid #000000;border-left:0При сравнении двух последовательностей каждый элемент спектральной матрицы гомологии отражает оценку подобия соответствующих участков последовательностей.002cm solid #000000;border-right:none;padding:0Также последовательность можно сравнивать с самой собой.097cm;"| Фурье| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| .025| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| '''3978'''| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:0.002cm solid #000000;padding:0.097cm;"| '''10000'''
|-| style="border-topПростейший «наивный» вариант алгоритма построения матрицы гомологии:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| Эрмита| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| .0015| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| 3502| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:0.002cm solid #000000;padding:0.097cm;"| 3500
|-* Загрузить входные файлы последовательностей.| style="border* По всем подпоследовательностям 1-topой последовательности:none;border-bottom:0** Подсчитать коэффициенты разложения подпоследовательности по выбранному ОНБ.002cm solid #000000;border-left:0** Вычислить норму вектора коэффициентов.002cm solid #000000;border** По всем подпоследовательностям 2-rightой последовательности:none;padding:0.097cm;"| Лагерра| style="border*** Подсчитать коэффициенты разложения подпоследовательности 2-top:none;border-bottom:0ой последовательности по выбранному ОНБ.002cm solid #000000;border*** Вычислить норму вектора коэффициентов разложения подпоследовательности 2-left:0ой последовательности.002cm solid #000000;border*** Подсчитать L<sub>2</sub>-right:none;padding:0расстояние между векторами коэффициентов разложения подпоследовательностей.097cm;"| *** Поделить подсчитанное расстояние на сумму норм векторов коэффициентов.0063| style="border*** Сохранить подсчитанное значение как (i, j)-top:none;border-bottom:0ый элемент матрицы гомологии.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| 3505| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:0.002cm solid #000000;padding:0* Записать матрицу гомологии в выходной файл.097cm;"| 3500
|-| style="border-topПодготовительный этап:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| Лежандра| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| .0225| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:none;padding:0.097cm;"| 3966| style="border-top:none;border-bottom:0.002cm solid #000000;border-left:0.002cm solid #000000;border-right:0.002cm solid #000000;padding:0.097cm;"| '''10000'''
|}* Подсчитать сетку Гаусса (то есть, корни n+1-ой функции базиса).* Подсчитать весовые и нормировочные коэффициенты.
=== Алгоритм разложения === «Наивный» вариант алгоритма разложения: * Интерполировать выбранную подпоследовательность длины N > n на подсчитанную сетку алгоритмом «ближайшего соседа».: То есть, по сути, не интерполировать её никак. Практика показала, что любая предварительная интерполяция никак не улучшает разложение по причине большой плотности точек в исходном сигнале и маленькой — в раскладываемом массиве.* Подсчитать в цикле <m>c_j = \sum_{i=1}^{n} y_i \cdot w_i \cdot f_j(x_i) \cdot r_j, j=1 \ldots n</m>, где:: <m>c_j</m> — j-ый коэффициент разложения сигнала <m>y_i</m>.: <m>w_i</m> — i-ый весовой коэффициент.: <m>f_j(x_i)</m> — значение j-ой функции базиса в i-ой точке сетки.: <m>r_j</m> — j-ый нормировочный коэффициент. Оптимизированный для рекуррентных соотношений алгоритм разложения: * Интерполировать выбранную подпоследовательность длины N > n на подсчитанную сетку алгоритмом «ближайшего соседа».* В цикле по ''i = 1..n'':** <m>c_i = 0</m>* В цикле по ''i = 1..n'':** Вычислить и сохранить в памяти все значения <m>f_j(x_i), j = 1 \ldots n</m> с помощью рекуррентных соотношений.** В цикле по ''j = 1..n'':*** <m>c_j = c_j + y_i \cdot f_j(x_i) \cdot r_j \cdot w_i</m> Псевдокод оптимизированного с учётом векторных операций алгоритма разложения здесь не приведён по причине его объёма. Кратко можно описать два момента: во-первых, циклы сменены местами — внешний цикл идёт по коэффициентам разложения, а не по функциям базиса, и во-вторых, на всех этапах используются векторные операции — сложения, умножения, возведения в квадрат и т. п. === Оптимизация === При реализации системы поиска повторов в виде программы учитывалась необходимость использования всех современных возможностей процессоров — ведь нужно понимать, что в наше время процессоры уже давно не i386, все суперскалярные, поддерживающие многопоточность, SIMD-инструкции (Single Instruction, Multiple Data) — инструкции, позволяющие за один такт выполнить несколько одинаковых операций сразу, аппаратно ускоренные математические функции и другие возможности поднятия производительности. Также не следует забывать, что большинство из этих возможностей успешно используется математическими пакетами вроде Matlab и Maple, популярными при тестировании и исследованиях математических методов. Поэтому, если забыть об этих возможностях в программе, можно испытать разочарование от скорости работы по сравнению с той же программой, реализованной с помощью математического пакета. К счастью, общий алгоритм разложения дискретизированных сигналов по классическим ортогональным базисам, являющийся просто алгоритмом вычисления соответствующего интеграла Гаусса, весьма прост и допускает оптимизацию также с помощью простых методов. Кроме того, ОСАМ позволяет и производить практически идеальное распараллеливание алгоритма по причине небольшого объёма необходимой памяти в случае, если не используется т. н. «индексация последовательности» — такой подход может быть полезен при вычислениях с массовым параллелизмом. ''Индексацией'' называется процесс предварительного разложения сравниваемой последовательности по выбранному ортогональному базису и сохранения в памяти всех векторов коэффициентов разложения для последующего использования. Достоинство индексации — отсутствие необходимости производить большой объём вычислений во вложенном цикле; её недостаток — существенное увеличение объёма используемой оперативной памяти и увеличение требований к пропускной способности памяти. Последнее особенно важно при массивно-параллельных вычислениях — отдельные процессоры, ядра или узлы кластера могут вообще не иметь общего доступа ко всей оперативной памяти системы, не говоря уже о существенном замедлении обмена данных между вычислителями и памятью в случае конкуретной работы с большой области памяти. Такая проблема присутствует даже на многоядерных стандартных настольных компьютерах и серверах нижнего класса — оперативная память обычно работает приблизительно со скоростью, равной четверти скорости процессоров и, начиная с определённого количества ядер/процессоров, индексация становится менее выгодной, чем могла бы быть, так как чипсет и оперативная память не могут обеспечить требуемую скорость обмена. Тем не менее, на обычных ПК и серверах нижнего класса наличие индексации хотя бы одной последовательности всё равно выгодно, поэтому при реализации был выбран следующий подход: индексация одной последовательности и разложение второй на лету. Соответственно, в любом случае — как в случае сравнения последовательности с самой собой, так и в случае сравнения двух последовательностей — вычисления коэффициентов разложения последовательностей происходят только 1 раз: первой при индексации, а второй во внешнем цикле. Реальный выигрыш в производительности засчёт чисто программной оптимизации достигает 10-20 раз на стандартных двухъядерных процессорах архитектуры Core 2. Очевидными вариантами достижения параллелизма в алгоритме поиска повторов являются библиотека OpenMP и ручная реализация распараллеливания на основе потоков — в UNIX-среде pthreads (POSIX threads — потоки POSIX), а в Windows-среде функций WINAPI. Можно было бы предположить, что использование библиотеки OpenMP упростит переносимость программы, однако, при переопределении всего лишь двух функций — создания потока и ожидания завершения потока (т. н. «join») — ручной подход достигает в точности такой же идеальной переносимости программы. Собственно говоря, функции создания потока и ожидания завершения потока являются настолько базовыми в любой библиотеке работы с потоками на любой платформе, поддерживающей потоки, что при реализации можно не бояться их потенциального отсутствия, тем более, когда на дворе 2009-ый год. Вместе с тем как раз реализация OpenMP потенциально существует не для всех ОС. Главным же минусом библиотеки OpenMP является то, что её работа построена на директивах компилятора, и в итоге транслируется обычно в код, постоянно создающий и завершающий вычислительные потоки, для каждой итерации распараллеливаемого цикла. Таким образом при использовании OpenMP либо приходится учитывать такое поведение, распараллеливая циклы с небольшими (по крайней мере, относительно) количествами итераций, ухудшая структуру кода и фактически сводя его логику к логике ручного распараллеливания, либо мириться с накладными расходами на распараллеливание, в нашем случае достигавшими 5-15 %. Таким образом, для параллелизма использовалось ручное разделение задачи на подзадачи и ручное управление вычислительными потоками. Для использования аппаратно-ускоренных и векторных (SIMD) инструкций использовалась библиотека Intel ''Integrated Performance Primitives'' (IPP). Ближайшая сравнение IPP — «векторный язык ассемблера», содержащий простые ''векторные'' «инструкции», а точнее оптимизированные функции-обёртки, для весьма широкого спектра задач — от сложений, умножений, корней и синусов, до узкоспециализированных функций ускорения декодирования аудио и видео, распознавания речи и т. п. Библиотека IPP даёт преимущества при использовании любых x86-процессоров, имеющих расширения наборов команд MMX, SSE, SSE2, SSE3 и т. п. Нужно отметить, что IPP сравнима в первую очередь действительно с языком ассемлера, так как не поддерживает трансляцию выражений над векторами, а только сами операции, реализованные в виде функций (аналог инструкций). Это, к сожалению, приводит к неочевидному «ассемблерному» коду следующего вида:  ippsCopy_64f(xn, wn, n); ippsSqr_64f_I(wn, n); ippsAddC_64f_I(-1, wn, n); ippsMulC_64f(wn, -1, tn, n); ippsSqrt_64f_I(tn, n); И последний важный момент — принцип «дискриминантности». Напомним, что расстояние между двумя векторами коэффициентов разложения определяется как <m>\frac{|a-b|}{|a|+|b|}</m>, где <m>|x|=\sqrt{\sum {x}_{i}^{2}}</m> Принцип «дискриминантности» же гласит очевидную вещь: если <m>\frac{\sqrt{{\sum }_{i=0}^{k}{({a}_{i}-{b}_{i})}^{2}}}{|a|+|b|}> \varepsilon</m> уже при k < n, суммирование можно не продолжать, т.к. ''меньше'' ε сумма квадратов уже не станет. Эта идея также использовалась при оптимизации алгоритма. Однако здесь возникает определённое препятствие: суммирование с постоянными условными проверками не векторизуется, т.е., при подсчёте нормы с учётом принципа "дискриминантности" IPP использовать мы уже не можем. Но так как IPP даёт весьма неплохой прирост производительности, можно применить следующий нетривиальный ход: сначала суммировать до ''k = d'', где d - делитель n, больший 1, с использованием векторных операций, потом проверять, не превышен ли порог, потом до ''k = 2d'', потом до ''k = 3d'', и т.д. === Алгоритм с учётом индексации === С учётом выбранного подхода — индексации одной последовательности и разложения другой «на лету» — алгоритм принимает следующий вид: * Загрузить входные файлы последовательностей.* ''Подсчитать и сохранить в памяти коэффициенты разложения всех подпоследовательностей 1-ой последовательности по выбранному ОНБ.''* ''Подсчитать и сохранить в памяти нормы всех векторов коэффициентов разложения этих подпоследовательностей.''* По всем ''сохранённым коэффициентам разложения подпоследовательностей'' 1-ой последовательности:** По всем подпоследовательностям 2-ой последовательности:*** Подсчитать коэффициенты разложения подпоследовательности 2-ой последовательности по выбранному ОНБ.*** Вычислить норму вектора коэффициентов разложения подпоследовательности 2-ой последовательности.*** Подсчитать L<sub>2</sub>-расстояние между векторами коэффициентов разложения подпоследовательностей.*** Поделить подсчитанное расстояние на сумму норм векторов коэффициентов.*** Сохранить подсчитанное значение как (i, j)-ый элемент матрицы гомологии.* Записать матрицу гомологии в выходной файл. === Алгоритм с учётом параллелизма === Изменения с учётом параллелизма тривиальны: наиболее внешние циклы разделяются на ''M'' частей и для обработки каждой части работы создаётся собственный поток. Далее главный поток приложения ожидает завершения всех созданных, т.е., ожидает окончания очередного этапа работы. * Загрузить входные файлы последовательностей.* ''Создать требуемое число M вычислительных потоков, далее, для каждого из них:''** ''Подсчитать и сохранить в памяти коэффициенты разложения своей <m>\frac{1}{M}</m>-ой части подпоследовательностей 1-ой последовательности по выбранному ОНБ.''** ''Подсчитать и сохранить в памяти нормы своей <m>\frac{1}{M}</m>-ой части векторов коэффициентов разложения этих подпоследовательностей.''* ''Создать требуемое число M вычислительных потоков, далее, для каждого из них:''** ''По своей <m>\frac{1}{M}</m>-ой части сохранённых коэффициентов разложения подпоследовательностей 1-ой последовательности'':*** По всем подпоследовательностям 2-ой последовательности:**** Подсчитать коэффициенты разложения подпоследовательности 2-ой последовательности по выбранному ОНБ.**** Вычислить норму вектора коэффициентов разложения подпоследовательности 2-ой последовательности.**** Подсчитать L<sub>2</sub>-расстояние между векторами коэффициентов разложения подпоследовательностей.**** Поделить подсчитанное расстояние на сумму норм векторов коэффициентов.**** Сохранить подсчитанное значение как (i, j)-ый элемент матрицы гомологии.* Записать матрицу гомологии в выходной файл. === Сравнение векторов с учётом векторных операций и дискриминантности === * Вычислить относительный порог <m>l = (\varepsilon \cdot (s_1 + s_2))²</m>, где s<sub>1</sub> и s<sub>2</sub> — нормы векторов.* Начальное значение ''f = 0''.* В цикле:** С помощью функции IPP <code>ippsNormDiffL2_64f</code> (или 32f, в зависимости от требуемой точности) вычислить норму разности очередных участков длины ''d'' сравниваемых векторов.** Добавить к ''f'' квадрат полученного значения.** Если ''f > l'', принять, что вектора «не подобны».* Если цикл завершился без принятия того, что вектора «не подобны», принять, что вектора подобны. === Сравнение ОНБ === Учитывая, что поиск повторов может осуществляться по выбору с использованием любого из ортогональных базисов, и что в библиотеке функций разложения их было реализовано 9 различных — базис Чебышева 1 рода, базис Чебышева 2 рода, дискретные косинусное и синусное преобразования, базис Фурье, базис Лежандра, базис Лагерра, базис Якоби и базис Эрмита — очевидным образом встаёт вопрос: а какой же из них «лучше» в задаче поиска повторов в последовательностях? А кроме того, каковы в целом критерии качества, по которым требуется производить сравнение базисов? Очевидным подходом к данному вопросу является критерий «максимум соотношения сигнал/шум в найденных в итоге повторах». Другой вариант — максимум средней длины найденных подобных участков, так как цель поиска повторов заключается в том, чтобы найти как можно более длинные подобные участки. Как можно оценить эту длину? Опишем простейший подход. Во-первых, нужно выбрать ширину скользящих окон и глубину разложения и выбрать некоторые тестовые данные, содержащие широкий спектр различных повторов — здесь хорошо подходит часть реальной ДНК-последовательности. Далее, используя различные базисы и подбирая порог сравнения (<m>\varepsilon</m>) такой, чтобы общее число найденных подобных участков было приблизительно равно, подсчитывать среднюю длину найденных подобных участков. Как вариант — можно вычислять медианное значение. В процессе реализации программы вначале был выбран базис Чебышева 1-го рода; потом пробовали базис Лежандра. Потом было высказано предположение о том, что базис Чебышева 2-го рода произведёт «революцию» по той причине, что имеет выпуклую весовую функцию и сильнее учитывает центр сравниваемого отрезка, чем края, но революции не произошло, результаты базиса Чебышева 2-го рода сильно похожи на базис Чебышева 1-го рода, и даже немного хуже, в том числе и по средней длине найденных повторов. Ниже приводится табличка с замерами средней длины найденных повторов на различных базисах и части генома мыши длиной 1.5 млн нуклеотидов в качестве тестовых данных. Сравнение производилось при приблизительно равных количествах найденных «подобных» участков — 5000. При выбранных настройках минимально возможная найденная длина подобного участка — 3500 нуклеотидов. <tab sep="tab" border="1" class="simpletable" head="topleft">- Eps Среднее МедианаЧебышева 1 рода .025 '''3978''' '''10000'''Чебышева 2 рода .0285 3882 3500ДКП .025 '''3978''' '''10000'''ДСП .021 3975 '''10000'''Фурье .025 '''3978''' '''10000'''Эрмита .0015 3502 3500Лагерра .0063 3505 3500Лежандра .0225 3966 '''10000'''</tab> Каковы выводы? По средней длине повтора лидирует базис Чебышев 1 рода, а базисы ДКП, ДСП и Фурье дают чрезвычайно похожие на него, практически идентичные, результаты. С небольшим отставанием следует базис Лежандра, далее — базис Чебышева 2 рода, а базисы Эрмита и Лагерра для поиска подобных участков не подходят вообще, чему есть простое математическое обоснование — оба они действуют на бесконечной полупрямой — либо <m>(0, +\inf)</m>, либо <m>(-\inf, +\inf)</m>. Вариантов значения медианной длины при этом было всего 2: 3500 (минимально возможная) или 10000. Медианная длина в данном случае отражает, фактически, «чистое» количество шума — мелких отрезков, и гласит, что приемлемый уровень шума дают базисы Чебышева 1 рода, ДКП, ДСП, Фурье и Лежандра. [[Категория:Статьи]][[Категория:УчёбаБиоинформатика]]