11.11.2014 Views

UMA ABORDAGEM EM HARDWARE PARA ... - Bioserver

UMA ABORDAGEM EM HARDWARE PARA ... - Bioserver

UMA ABORDAGEM EM HARDWARE PARA ... - Bioserver

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>UMA</strong> <strong>ABORDAG<strong>EM</strong></strong> <strong>EM</strong> <strong>HARDWARE</strong> <strong>PARA</strong><br />

ALGORITMOS DE COM<strong>PARA</strong>ÇÃO DE SEQÜÊNCIAS<br />

BASEADOS <strong>EM</strong> PROGRAMAÇÃO DINÂMICA<br />

LUÍS GUSTAVO DE AQUINO CARVALHO<br />

DISSERTAÇÃO DE MESTRADO <strong>EM</strong> CIÊNCIA DA COMPUTAÇÃO<br />

DEPARTAMENTO DE CIÊNCIA DA COMPUTAÇÃO


UNIVERSIDADE DE BRASÍLIA<br />

INSTITUTO DE CIÊNCIAS EXATAS<br />

DEPARTAMENTO DE CIÊNCIA DA COMPUTAÇÃO<br />

<strong>UMA</strong> <strong>ABORDAG<strong>EM</strong></strong> <strong>EM</strong> <strong>HARDWARE</strong> <strong>PARA</strong><br />

ALGORITMOS DE COM<strong>PARA</strong>ÇÃO DE SEQÜÊNCIAS<br />

BASEADOS <strong>EM</strong> PROGRAMAÇÃO DINÂMICA<br />

LUÍS GUSTAVO DE AQUINO CARVALHO<br />

ORIENTADOR: PROF. DR. RICARDO PEZZUOL JACOBI<br />

DISSERTAÇÃO DE MESTRADO <strong>EM</strong><br />

CIÊNCIA DA COMPUTAÇÃO<br />

PUBLICAÇÃO: XXX/2003<br />

BRASÍLIA/DF, DEZ<strong>EM</strong>BRO/2003.


UNIVERSIDADE DE BRASÍLIA<br />

INSTITUTO DE CIÊNCIAS EXATAS<br />

DEPARTAMENTO DE CIÊNCIA DA COMPUTAÇÃO<br />

<strong>UMA</strong> <strong>ABORDAG<strong>EM</strong></strong> <strong>EM</strong> <strong>HARDWARE</strong> <strong>PARA</strong><br />

ALGORITMOS DE COM<strong>PARA</strong>ÇÃO DE SEQÜÊNCIAS<br />

BASEADOS <strong>EM</strong> PROGRAMAÇÃO DINÂMICA<br />

LUÍS GUSTAVO DE AQUINO CARVALHO<br />

DISSERTAÇÃO DE MESTRADO SUBMETIDA AO DEPARTAMENTO DE CIÊNCIA<br />

DA COMPUTAÇÃO DO INSTITUTO DE CIÊNCIAS EXATAS DA UNIVERSIDADE<br />

DE BRASÍLIA, COMO PARTE DOS REQUISITOS NECESSÁRIOS <strong>PARA</strong> A OBTEN-<br />

ÇÃO DO GRAU DE MESTRE.<br />

APROVADA POR:<br />

PROF. DR. RICARDO PEZZUOL JACOBI (UnB)<br />

(ORIENTADOR)<br />

PROF a DR a MARIA <strong>EM</strong>ÍLIA MACHADO TELLES WALTER (UnB)<br />

(EXAMINADOR INTERNO)<br />

PROF. DR. JOSÉ CAMARGO DA COSTA (UnB)<br />

(EXAMINADOR EXTERNO)<br />

BRASÍLIA/DF, 17 DE DEZ<strong>EM</strong>BRO DE 2003.<br />

ii


FICHA CATALOGRÁFICA<br />

CARVALHO, LUÍS GUSTAVO DE AQUINO<br />

Uma Abordagem em Hardware para Algoritmos de Comparação de Seqüências<br />

Baseados em Programação Dinâmica [Distrito Federal] 2003.<br />

xiv, 100 p., 297mm (CIC/IE/UnB, Mestre, Ciência da Computação, 2003).<br />

Dissertação de Mestrado — Universidade de Brasília. Instituto de Ciências<br />

Exatas. Departamento de Ciência da Computação.<br />

1. Comparação de seqüências 2. Smith-Waterman<br />

3. Arquiteturas Reconfiguráveis 4. FPGA<br />

5. Arquiteturas Sistólicas<br />

I. CIC/IE/UnB II. Título (série)<br />

REFERÊNCIA BIBLIOGRÁFICA<br />

CARVALHO, L. G. A. (2003). Uma Abordagem em Hardware para Algoritmos de<br />

Comparação de Seqüências Baseados em Programação Dinâmica. Dissertação de Mestrado,<br />

Publicação XXX/2003, Departamento de Ciência da Computação, Universidade de<br />

Brasília, Brasília, DF, 100 p.<br />

CESSÃO DE DIREITOS<br />

NOME DO AUTOR: Luís Gustavo de Aquino Carvalho<br />

TÍTULO DA DISSERTAÇÃO DE MESTRADO: Uma Abordagem em Hardware para<br />

Algoritmos de Comparação de Seqüências Baseados em Programação Dinâmica.<br />

GRAU / ANO: Mestre / 2003<br />

É concedida à Universidade de Brasília permissão para reproduzir cópias desta dissertação<br />

de mestrado e para emprestar ou vender tais cópias somente para propósitos acadêmicos e<br />

científicos. O autor reserva outros direitos de publicação e nenhuma parte desta dissertação<br />

de mestrado pode ser reproduzida sem a autorização por escrito do autor.<br />

Luís Gustavo de Aquino Carvalho<br />

iii


iv<br />

A minha família.


Agradecimentos<br />

Aos meus pais, pela formação que me foi dada e por todo o amor recebido.<br />

Ao meu orientador, Prof. Ricardo Jacobi, por sua paciência, compreensão<br />

e excelência acadêmica.<br />

Aos meus amigos, em especial ao Antônio Marcelo que me apresentou ao<br />

meu orientador e me incentivou a trabalhar com arquiteturas reconfiguráveis;<br />

à Marie, pela grande ajuda durante a conclusão das disciplinas, além de grande<br />

companheira; à Márcia, pela sua prontidão em elucidar dúvidas; ao Hugo e<br />

Cristiano, pelas constantes trocas de idéias e pela valiosa ajuda na formatação<br />

em L A TEX desta dissertação.<br />

E principalmente à minha esposa e filhos, por todos os momentos que deixei<br />

de estar com eles para me dedicar à essa dissertação.<br />

v


<strong>UMA</strong> <strong>ABORDAG<strong>EM</strong></strong> <strong>EM</strong> <strong>HARDWARE</strong> <strong>PARA</strong><br />

ALGORITMOS DE COM<strong>PARA</strong>ÇÃO DE SEQÜÊNCIAS<br />

BASEADOS <strong>EM</strong> PROGRAMAÇÃO DINÂMICA<br />

Resumo<br />

Pesquisas em bancos de dados biológicos utilizam algoritmos de comparação<br />

de seqüências para busca de similaridades entre as seqüências armazenadas<br />

nestes bancos e a seqüência consultada. Embora os algoritmos de comparação<br />

baseados em programação dinâmica retornem uma resposta ótima, eles não<br />

são usados na prática dos laboratórios de Bioinformática, pois a complexidade<br />

quadrática de tempo é um fator limitante em virtude do considerável tamanho<br />

das seqüências biológicas.<br />

Métodos mais rápidos, baseados em probabilidades, mas sem garantia de<br />

exatidão, são preferidos por possuírem uma complexidade linear de tempo.<br />

Assim, a aplicação de técnicas que acelerem e viabilizem a utilização dos<br />

algoritmos baseados em programação dinâmica constitui uma importante contribuição<br />

para a qualidade da informação produzida.<br />

Dentre essas técnicas está a criação de um hardware dedicado para uma<br />

aplicação específica. Nesse escopo, os sistemas reconfiguráveis baseados em<br />

FPGA’s encontram grande aplicação, pois permitem a prototipação em hardware<br />

de algoritmos bastante complexos com baixos custos.<br />

Este trabalho propõe e implementa em FPGA um hardware baseado em<br />

uma arquitetura sistólica que lineariza o tempo de execução dos algoritmos<br />

baseados em programação dinâmica.<br />

A fim de validar os resultados obtidos foram realizadas comparações com<br />

outras implementações seqüenciais e paralelas desses algoritmos.<br />

vi


A <strong>HARDWARE</strong> APPROACH<br />

TO SEQUENCE COMPARISON ALGORITHMS<br />

BASED ON DYNAMIC PROGRAMMING<br />

Abstract<br />

Sequence comparison algorithms are used in biological database searches<br />

in order to find similarities between the database sequences and a query sequence.<br />

Although the comparison algorithms based on dynamic programming<br />

techniques produces an optimal result, they are not used by Bioinformatics<br />

laboratories, once its quadratic time complexity is prohibitive in view of the<br />

considerable size of the biological sequences.<br />

Faster methods, based on probabilities, but without precision guarantee,<br />

are preferred for its linear time complexity.<br />

Therefore, improving sequence comparison algorithms based on dynamic<br />

programming constitutes an important contribution to the quality of the information<br />

produced.<br />

A dedicated hardware for an specific application could be one of this solutions.<br />

In this scope, reconfigurable systems find enormous application because<br />

they provide rapid prototyping of complex algorithms with small costs.<br />

In this work, we propose and implement in FPGA a systolic architecture<br />

based hardware which turns to linear the time complexity of the comparison<br />

algorithms based on dynamic programming.<br />

In order to validate the results produced by our implementation, we compared<br />

our results with the ones produced by other sequential and parallel<br />

implementations of the same algorithm.<br />

vii


Sumário<br />

1 INTRODUÇÃO 1<br />

1.1 Escopo do Trabalho . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1<br />

1.1.1 Projeto Genoma Humano . . . . . . . . . . . . . . . . . . . . . . . 1<br />

1.1.2 Pesquisas no Brasil . . . . . . . . . . . . . . . . . . . . . . . . . . . 3<br />

1.1.3 Bioinformática e Biologia Computacional . . . . . . . . . . . . . . . 4<br />

1.1.4 Pesquisas em Bancos de Dados Biológicos . . . . . . . . . . . . . . 5<br />

1.1.5 Algoritmos para Comparação de Seqüências . . . . . . . . . . . . . 6<br />

1.2 Revisão Bibliográfica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7<br />

1.3 Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />

1.4 Organização da Dissertação . . . . . . . . . . . . . . . . . . . . . . . . . . 10<br />

2 FUNDAMENTAÇÃO TEÓRICA 11<br />

2.1 Biologia Molecular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11<br />

2.1.1 Ácidos Nucléicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11<br />

2.1.1.1 DNA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13<br />

2.1.1.2 RNA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14<br />

2.1.2 Aminoácidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15<br />

2.1.3 Proteínas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16<br />

2.1.4 Genes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18<br />

2.1.5 Genética Molecular . . . . . . . . . . . . . . . . . . . . . . . . . . . 19<br />

2.1.6 Síntese Protéica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20<br />

2.2 Algoritmos para Comparação de Seqüências Baseados em Programação<br />

Dinâmica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22<br />

viii


2.2.1 Alinhamento de seqüências . . . . . . . . . . . . . . . . . . . . . . . 22<br />

2.2.2 Algoritmos baseados em programação dinâmica . . . . . . . . . . . 24<br />

2.2.2.1 Comparação global . . . . . . . . . . . . . . . . . . . . . . 24<br />

2.2.2.2 Comparação local . . . . . . . . . . . . . . . . . . . . . . . 27<br />

3 <strong>HARDWARE</strong> 30<br />

3.1 Sistemas Dedicados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30<br />

3.2 Arquiteturas Sistólicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33<br />

3.3 Sistemas Reconfiguráveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35<br />

3.3.1 FPGA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38<br />

3.3.2 Síntese de sistemas reconfiguráveis . . . . . . . . . . . . . . . . . . 39<br />

3.3.3 Linguagens de descrição de hardware e VHDL . . . . . . . . . . . . 41<br />

3.4 Somadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44<br />

3.4.1 Meio-somador (half adder) . . . . . . . . . . . . . . . . . . . . . . . 44<br />

3.4.2 Somador completo (full adder) . . . . . . . . . . . . . . . . . . . . 45<br />

3.4.3 Somador ripple carry . . . . . . . . . . . . . . . . . . . . . . . . . . 45<br />

3.4.4 Somador com “vai-um” antecipado (carry look ahead) . . . . . . . . 46<br />

3.4.5 Subtrator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48<br />

3.5 Matrizes esparsas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48<br />

3.5.1 Compressed Row Storage (CRS) . . . . . . . . . . . . . . . . . . . . 49<br />

3.5.2 Compressed Column Storage (CCS) . . . . . . . . . . . . . . . . . . 50<br />

3.5.3 Compressed Diagonal Storage (CDS) . . . . . . . . . . . . . . . . . 50<br />

3.5.4 Jagged Diagonal Storage (JDS) . . . . . . . . . . . . . . . . . . . . 51<br />

4 DESCRIÇÃO DA IMPL<strong>EM</strong>ENTAÇÃO 52<br />

4.1 Aplicação de Estruturas Paralelas na comparação de seqüências . . . . . . 52<br />

4.2 Dependência de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53<br />

4.3 Plataforma Utilizada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53<br />

4.4 Descrição Geral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53<br />

4.4.1 Estrutura sistólica . . . . . . . . . . . . . . . . . . . . . . . . . . . 54<br />

ix


4.4.2 Otimização de Utilização de Espaço e Armazenamento dos Alinhamentos<br />

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66<br />

4.4.3 Outras otimizações . . . . . . . . . . . . . . . . . . . . . . . . . . . 70<br />

5 RESULTADOS 72<br />

5.1 Validação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72<br />

5.2 Desempenho . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77<br />

6 CONCLUSÕES 81<br />

x


Lista de Tabelas<br />

1.1 Projetos Regionais de Seqüenciamento no Brasil. . . . . . . . . . . . . . . . 4<br />

2.1 Principais diferenças entre o DNA e o RNA. . . . . . . . . . . . . . . . . . 15<br />

2.2 Os 20 diferentes tipos de aminoácidos encontrados na natureza. . . . . . . 17<br />

3.1 Tabela-verdade do meio-somador (half adder). . . . . . . . . . . . . . . . . 44<br />

3.2 Tabela-verdade do somador completo (full adder). . . . . . . . . . . . . . . 45<br />

5.1 Quantidade de elementos lógicos utilizados e freqüência máxima de operação<br />

para diferentes comprimentos do vetor sistólico. . . . . . . . . . . . . . . . 77<br />

5.2 Comparação de velocidade entre uma implementação seqüencial, diversas<br />

paralelas e em hardware do algoritmo baseado em programação dinâmica. . 80<br />

xi


Lista de Figuras<br />

1.1 Crescimento do GenBank. . . . . . . . . . . . . . . . . . . . . . . . . . . . 6<br />

1.2 Mapeamento do cálculo da matriz de similaridade em uma estrutura sistólica<br />

bidirecional. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7<br />

2.1 Bases Nitrogenadas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12<br />

2.2 Tipos de Açúcares. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12<br />

2.3 A estrutura de uma molécula de DNA, formada por uma dupla fita. (a)<br />

Forma helicoidal da dupla cadeia. (b) Forma esquemática da dupla cadeia,<br />

onde podemos visualizar a ligação entre as moléculas de açúcar (S)<br />

e de fosfato (P), em cada uma das fitas, e o emparelhamento das bases<br />

Adenina/Timina e Citosina/Guanina, entre as duas fitas. . . . . . . . . . . 13<br />

2.4 Dupla fita de DNA, observando-se o pareamento das bases A-T e C-G. . . 14<br />

2.5 Exemplo de alguns grupos orgânicos. . . . . . . . . . . . . . . . . . . . . . 15<br />

2.6 Estrutura e exemplos de alguns aminoácidos. . . . . . . . . . . . . . . . . . 16<br />

2.7 União de dois aminoácidos por uma ligação peptídica. . . . . . . . . . . . . 16<br />

2.8 Visão esquemática dos genes, cromossomos e genoma. . . . . . . . . . . . . 19<br />

2.9 Código genético. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19<br />

2.10 Duplicação do DNA. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20<br />

2.11 Representação esquemática da transcrição e tradução. . . . . . . . . . . . . 21<br />

2.12 Detalhamento do processo de tradução. . . . . . . . . . . . . . . . . . . . . 21<br />

2.13 Pontuação de um possível alinhamento entre CCTAGA e CTATGCAC. . . 23<br />

2.14 Matriz de similaridades das seqüências x = AACGT e y = AGC. . . . . . 26<br />

2.15 Obtenção do melhor alinhamento global. . . . . . . . . . . . . . . . . . . . 27<br />

3.1 Aspecto geral de uma arquitetura sistólica. . . . . . . . . . . . . . . . . . . 33<br />

3.2 Alguns tipos de estruturas sistólicas. . . . . . . . . . . . . . . . . . . . . . 34<br />

3.3 Modelos segundo a classificação de Page. . . . . . . . . . . . . . . . . . . . 37<br />

xii


3.4 Estrutura interna de um FPGA. . . . . . . . . . . . . . . . . . . . . . . . . 39<br />

3.5 Fluxo de projeto utilizando FPGAs. . . . . . . . . . . . . . . . . . . . . . . 40<br />

3.6 Diagrama esquemático do meio-somador. . . . . . . . . . . . . . . . . . . . 45<br />

3.7 Diagrama esquemático do somador completo. . . . . . . . . . . . . . . . . 46<br />

3.8 Diagrama de um somador ripple carry de 4 bits. . . . . . . . . . . . . . . . 46<br />

3.9 Diagrama de um somador de 4 bits com “vai-um” antecipado. . . . . . . . 47<br />

3.10 Diagrama de um somador de 16 bits com “vai-um” antecipado. . . . . . . . 48<br />

3.11 Diagrama de um somador-subtrator de 4 bits. . . . . . . . . . . . . . . . . 48<br />

4.1 Paralelização do cálculo da matriz de similaridade. . . . . . . . . . . . . . . 53<br />

4.2 Matriz de similaridade para as seqüências ACATAGGCAT e CATAAGGCT. 54<br />

4.3 Tipos de emulação da matriz de similaridade. . . . . . . . . . . . . . . . . 55<br />

4.4 Estrutura linear sistólica uniderecional. . . . . . . . . . . . . . . . . . . . . 56<br />

4.5 Estrutura interna inicial do elemento de processamento. . . . . . . . . . . . 57<br />

4.6 Fluxo interno dos dados dentro do elemento de processamento. . . . . . . . 58<br />

4.7 Dinâmica do sistema para vários elementos de processamento. . . . . . . . 58<br />

4.8 Somador de 8 bits com a constante -2 embutida no mesmo. . . . . . . . . . 60<br />

4.9 Cálculo do valor da diagonal. . . . . . . . . . . . . . . . . . . . . . . . . . 61<br />

4.10 Cálculo do valor relativo à inserção do espaço. . . . . . . . . . . . . . . . . 61<br />

4.11 Codificação dos vetores da matriz de similaridade. . . . . . . . . . . . . . . 63<br />

4.12 Tipos de zeros existentes na matriz de similaridade. . . . . . . . . . . . . . 67<br />

4.13 Verificação antecipada para saber se o zero fará parte de uma seqüência. . 68<br />

4.14 Posição das bases para a verificação antecipada. . . . . . . . . . . . . . . . 69<br />

4.15 Novo formato do dado fornecido à memória externa. . . . . . . . . . . . . . 70<br />

5.1 Matrizes de similaridade para as seqüências CATAG e ATAGC e para CA-<br />

TAG e CATGA. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73<br />

5.2 Comparação entre as seqüências CATAG e ATAGC. . . . . . . . . . . . . . 73<br />

5.3 Comparação entre as seqüências CATAG e CATGA. . . . . . . . . . . . . . 75<br />

5.4 Comparação entre as seqüências ACATAGGCAT e CATAAGGCT. . . . . 76<br />

5.5 Freqüência máxima de operação x Quantidade de células do vetor. . . . . . 78<br />

xiii


5.6 Quantidade de elementos lógicos utilizados no FPGA x Quantidade de<br />

células do vetor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79<br />

xiv


Capítulo 1<br />

INTRODUÇÃO<br />

1.1 Escopo do Trabalho<br />

Há 50 anos, no dia 7 de março de 1953, no laboratório Cavendish, na Inglaterra, Francis<br />

Crick e James Watson concluíram que a molécula do DNA tem a estrutura de uma dupla<br />

hélice, uma descoberta que daria novos rumos à ciência. No dia 25 de abril daquele<br />

ano, a revista Nature publicou o artigo Molecular Structure of Nucleic Acids (Estrutura<br />

Molecular dos Ácidos Nucleicos) [72], primeiro de uma série sobre o tema. Com menos de<br />

mil palavras e um gráfico simplificado, o trabalho descrevia a estrutura da molécula.<br />

A partir de então, a Biologia Molecular tornou-se, de fato, uma ciência. Incontáveis<br />

pesquisas começaram a serem feitas para melhor compreender a estrutura e o funcionamento<br />

da genética dos seres vivos. Essas pesquisas proporcionaram inúmeros avanços nas<br />

técnicas da Biologia Molecular que aceleraram o processo de descoberta e descrição da<br />

estrutura e funcionalidade dos genes. Entre os avanços, o aparecimento de seqüenciadores<br />

automáticos capazes de gerar dados genômicos em grande escala e de ferramentas<br />

de análise computacional comparativa entre seqüências trouxeram um grande progresso<br />

nessa nova área do conhecimento biológico.<br />

1.1.1 Projeto Genoma Humano<br />

Um importante marco para o atual desenvolvimento da Biologia Molecular foi o Projeto<br />

Genoma Humano, um empreendimento internacional iniciado formalmente em 1990 e<br />

projetado para durar 15 anos, com os seguintes objetivos:<br />

• Identificar e fazer o mapeamento dos 80 mil genes que se calculava existirem no<br />

DNA das células do corpo humano;<br />

• Determinar as seqüências dos 3 bilhões de bases químicas que compõem o DNA<br />

humano;<br />

• Armazenar essas informações em bancos de dados, desenvolver ferramentas eficientes<br />

para analisar esses dados e torná-los acessíveis para novas pesquisas biológicas.<br />

1


Como parte deste empreendimento, paralelamente foram desenvolvidos estudos com<br />

outros organismos selecionados, principalmente microorganismos considerados modelos<br />

biológicos, tais como Saccharomyces cerevisiae e Drosophila melanogaster, entre outros.<br />

O objetivo era desenvolver e aperfeiçoar novas técnicas de análise e também auxiliar o<br />

trabalho de interpretar a complexa função genética humana. Como existe uma ordem<br />

subjacente a toda a diversidade da vida e como todos os organismos se relacionam através<br />

de semelhanças em suas seqüências de DNA, o conhecimento adquirido a partir de genomas<br />

não-humanos levaria a novas descobertas na biologia humana.<br />

Em 1990, ao iniciar-se o PGH, apenas 4550 genes humanos haviam sido identificados;<br />

cerca de 1500 genes haviam sido associados a localizações específicas nos 46 cromossomos, e<br />

apenas algumas, dentre cerca de 4000 doenças genéticas existentes, haviam sido entendidas<br />

em um nível molecular.<br />

Em 12 de fevereiro de 2001, simultaneamente ao anúncio da empresa norte-americana<br />

Celera, o PGH anunciou as primeiras transcrições quase completas do código genético<br />

humano. O número de genes existentes, segundo os cálculos de ambas as equipes de<br />

pesquisadores, não chega a 40 mil. Os resultados foram publicados em duas revistas<br />

diferentes. A revista inglesa Nature [3] publicou o trabalho dos pesquisadores do PGH,<br />

liderados por Francis Collins, e a norte-americana Science, o dos pesquisadores da Celera,<br />

liderados pelo empresário-cientista Craig Venter.<br />

Em 14 de abril de 2003, o consórcio internacional que constituiu o Projeto Genoma<br />

Humano anunciou oficialmente a conclusão do seqüenciamento dos 3 bilhões de bases<br />

do DNA da espécie humana. Liderados pelo Instituto Nacional de Pesquisa do Genoma<br />

Humano (NHGRI), nos EUA e pelo Instituto Sanger, no Reino Unido, o projeto durou<br />

13 anos e, segundo se afirmou, consumiu 2,7 bilhões de dólares para se chegar à meta<br />

proposta em 1990, de decifrar a estrutura do DNA humano com 99,9% de precisão.<br />

Embora o resultado desse grandioso empreendimento mundial deva ser comemorado,<br />

ele é apenas a conclusão da etapa inicial das pesquisas sobre o assunto. A analogia que<br />

se faz é a seguinte: os bilhões de elementos que estão sendo decifrados nada mais são do<br />

que as “letras”. Depois será preciso entender as “palavras” (mapeamento dos genes) e a<br />

“linguagem”, que correspondem às funções que esses genes desempenham.<br />

Essa linguagem contida na molécula de DNA serve para ordenar a fabricação das<br />

proteínas, que são usadas pelos seres vivos - das bactérias aos humanos - para executar<br />

tarefas vitais como movimentar-se, respirar, pensar e gastar energia.<br />

O objetivo agora, depois de se conhecer o genoma humano completo, assim como o de<br />

outros organismos, é determinar a composição, estrutura, e funções de todas as proteínas<br />

do corpo para saber como elas interagem entre si. Ao conjunto de proteínas que intervêm<br />

nos processos biológicos de uma espécie é dado o nome de proteoma.<br />

Empresas e laboratórios públicos e privados já estão na corrida para entender o proteoma,<br />

embora este seja sem dúvida muito mais extenso e complicado que o genoma.<br />

2


Enquanto o DNA possui somente quatro bases nitrogenadas, as proteínas são compostas<br />

de aminoácidos, dos quais existem 20 tipos diferentes. Além disso, o DNA está localizado<br />

no núcleo de qualquer célula, o que facilita a sua obtenção e purificação, já muitas<br />

proteínas só estão presentes em alguns tipos de células, e somente em certas fases de seu<br />

desenvolvimento.<br />

Por último, não basta enumerar a seqüência de aminoácidos que forma a proteína,<br />

porque tão importante quanto a seqüência é a estrutura tridimensional que ela possui,<br />

interferindo decisivamente no papel que ela realiza.<br />

Conhecer como funciona o proteoma é um processo complexo, porque na maioria das<br />

vezes a proteína não age sozinha realizando determinada tarefa, mas sim é uma interação<br />

entre elas que vai condicionar o processo. Uma forma de conhecer as funções das proteínas,<br />

é compará-la a funções conhecidas, tanto na própria espécie, quanto em outras, já que a<br />

maior parte das proteínas se conservam em muitos organismos, mesmo que alguns se<br />

encontrem filogeneticamente distantes entre si.<br />

A corrida ao grande mapa das proteínas, ou proteoma, será um dos maiores desafios<br />

científicos da próxima década.<br />

1.1.2 Pesquisas no Brasil<br />

A participação do Brasil na área de pesquisas genômicas teve início em 1998 a partir<br />

do financiamento, pela FAPESP (Fundação de Amparo à Pesquisa do Estado de São<br />

Paulo), de um instituto virtual formado por um consórcio de laboratórios, responsável<br />

pelo seqüenciamento e análise de nucleotídeos, denominado ONSA (Organization for Nucleotide<br />

Sequencing and Analysis) [53]. O primeiro resultado importante desse instituto<br />

com reconhecimento internacional ocorreu em 2000 com a publicação do genoma do fitopatógeno<br />

Xylella fastidiosa [65], agente etiológico da Citrus Variegated Chlorosis (CVC),<br />

mais conhecida como praga do amarelinho. Essa doença destrói lavouras de laranja,<br />

principalmente no Estado de São Paulo, ocasionando prejuízos econômicos de grandes<br />

proporções.<br />

Motivada pelo sucesso alcançado, a FAPESP resolveu investir em projetos mais ambiciosos,<br />

como o do mapeamento do genoma da cana-de-açúcar, do câncer humano (em<br />

colaboração com o Instituto Ludwig para Pesquisa do Câncer), do café e também de vários<br />

organismos e pragas como o Xylella fastidiosa de videira, o Xanthomonas campestris, o<br />

Xanthomonas axonopodis e o Leifsonia xyli, além de subsidiar outros projetos como o<br />

do mapeamento do genoma funcional do Schistosoma mansoni. Outro ponto que merece<br />

destaque é a criação das redes de seqüenciamento, que ocorreu tanto no âmbito nacional<br />

como no regional. No âmbito nacional há dois projetos: o Projeto Genoma Brasileiro,<br />

que seqüenciou a bactéria Chromobacterium violaceum, cujos resultados podem ser potencialmente<br />

aplicados no controle da doença de chagas e da leishmaniose, e o Projeto<br />

Genolyptus, responsável pelo seqüenciamento do eucalipto (Fundo Verde-Amarelo/MCT).<br />

3


No âmbito regional surgiram várias redes com projetos de seqüenciamento de organismos<br />

importantes, especialmente para o controle de pragas e doenças, conforme indicado na<br />

tabela 1.1.<br />

Tabela 1.1: Projetos Regionais de Seqüenciamento no Brasil.<br />

Rede Regional<br />

Organismo Alvo<br />

Rede Genoma do Estado de Minas Gerais<br />

Schistosoma mansoni<br />

Rede Genoma Nordeste<br />

Leishmania chagasi<br />

Rede Genômica do Estado da Bahia e São Paulo Crinipellis perniciosa<br />

Rede Genoma do Consórcio<br />

do Instituto de Biologia Molecular do Paraná, Trypanossoma cruzi<br />

FIO-CRUZ e Universidade de Mogi das Cruzes<br />

Programa Genoma do Estado do Paraná<br />

Herbaspirillum seropedicae<br />

Rede Genoma do Rio de Janeiro<br />

Gluconacetobacter diazotrophicus<br />

Rede Sul de Análise de Genomas e Biologia Estrutural Mycoplasma hyopneumoniae<br />

Rede Genoma Centro-Oeste<br />

Paracoccidioides brasiliensis<br />

Esses projetos colocam o Brasil no grupo dos países com tecnologia e infra-estrutura<br />

suficientes para conduzirem pesquisas na área genômica. Isso é de importância estratégica<br />

vital, pois permite que problemas específicos do nosso país, que afetam nossa população<br />

e/ou produção agropecuária, sejam resolvidos sem depender dos laboratórios estrangeiros.<br />

Além disso, esses projetos estimulam o desenvolvimento de novas tecnologias e a capacitação<br />

e de profissionais especializados, o que contribui para colocar o Brasil em posição<br />

de igualdade perante a comunidade científica internacional nessa área.<br />

1.1.3 Bioinformática e Biologia Computacional<br />

O Projeto Genoma Humano e os crescentes avanços da tecnologia tem permitido aos<br />

laboratórios de Biologia Molecular fornecerem detalhes cada vez mais precisos sobre as<br />

estruturas estudadas. O enorme volume de informações acumulado desde então e a necessidade<br />

de trabalhar esses dados eficientemente criou uma série de problemas que são, por<br />

natureza, interdisciplinares. Em particular, as teorias da matemática e da computação<br />

tornaram-se fundamentais no processo de manipulação de dados científicos dentro da Biologia<br />

Molecular [64].<br />

Isso levou ao surgimento de duas áreas de pesquisa intimamente ligadas:<br />

• A Bioinformática, que tem como finalidade principal gerar novos conhecimentos a<br />

partir da grande quantidade de dados que vêm sendo obtidos sobre seqüências de<br />

DNA e proteínas e pode ser descrita como a aquisição, organização, armazenamento<br />

e análise dessas informações biológicas;<br />

• e a Biologia Computacional, que estuda o desenvolvimento de algoritmos e programas<br />

computacionais para auxiliar a Bioinformática.<br />

4


A Bioinformática, apesar de ser um campo relativamente novo, tem evoluído dramaticamente<br />

nos últimos anos e, hoje, é fundamental para as pesquisas realizadas em Biologia<br />

Molecular [21].<br />

Há três objetivos principais dentro da Bioinformática. O primeiro é prover um meio de<br />

organizar os dados biológicos de forma a tornar fácil o acesso às informações e a submissão<br />

de novos dados à medida que estes são gerados. Diversos bancos de dados biológicos foram<br />

e continuam sendo criados com esse objetivo. O segundo objetivo é o desenvolvimento<br />

de ferramentas para processar os dados armazenados e extrair diversas informações ali<br />

contidas. O terceiro objetivo é a análise dos resultados gerados por essas ferramentas<br />

para interpretar as informações de uma maneira que seja biologicamente consistente e<br />

relevante [44].<br />

1.1.4 Pesquisas em Bancos de Dados Biológicos<br />

Tradicionalmente, pesquisas em Biologia investigavam um sistema isoladamente e o<br />

comparavam com outros poucos sistemas relacionados. A Bioinformática permitiu conduzir<br />

análises globais envolvendo um volume muito maior de dados, de forma a descobrir<br />

princípios comuns e características importantes mais facilmente.<br />

Um dos problemas fundamentais nessa área é a comparação entre duas ou mais seqüências<br />

de DNA ou proteínas, servindo como base para a solução de uma grande variedade de<br />

problemas. A comparação entre seqüências é uma tarefa computacionalmente intensa e<br />

lenta. Primeiro, porque os algoritmos utilizados possuem uma complexidade de tempo significativa<br />

pois devem permitir mutações genéticas, ou seja, inserções, remoções ou substituições<br />

nas seqüências comparadas. Segundo, porque o tamanho dessas seqüências podem<br />

ser muito grande, da ordem de milhões de caracteres.<br />

Como os repositórios dessas informações vêm aumentando de tamanho a taxas elevadas,<br />

métodos cada vez mais rápidos e eficientes para a comparação de seqüências se<br />

tornam necessários para se manterem eficientes em relação ao crescente tamanho dos bancos<br />

de dados. Por exemplo, o GenBank, um dos principais bancos de dados públicos<br />

sobre informações genéticas, tem sido alimentado a uma taxa quase exponencial com o<br />

tempo (figura 1.1).<br />

A análise de uma seqüência obtida dentro de um projeto de seqüenciamento é iniciada<br />

comparando-a com as seqüências já descobertas e analisadas, armazenadas nesses bancos<br />

de dados, para que o relacionamento existente entre elas possa permitir estabelecer<br />

a determinação de sua função, estrutura, características evolucionárias e influência em<br />

doenças, entre outras.<br />

5


Figura 1.1: Crescimento do GenBank.<br />

1.1.5 Algoritmos para Comparação de Seqüências<br />

O algoritmo com melhores resultados teóricos foi proposto por Smith e Waterman [66],<br />

baseado em técnicas de programação dinâmica, com o intuito de mostrar as posições<br />

“similares” entre duas seqüências. No entanto, conforme já citado, devido ao considerável<br />

tamanho de algumas seqüências biológicas, a computação por programação dinâmica,<br />

que tem complexidade quadrática de tempo e espaço, torna-se inviável com os recursos<br />

computacionais existentes atualmente.<br />

Assim surgiram os métodos heurísticos de comparação de seqüências, baseados em probabilidades<br />

estatísticas acerca destas seqüências. Estes métodos possuem complexidade<br />

linear de tempo, o que torna as pesquisas mais rápidas, embora não garantam a produção<br />

de resultados ótimos. Apesar desta desvantagem, as ferramentas baseadas nestes métodos<br />

têm sido bem aceitas e amplamente utilizadas pelos laboratórios de seqüenciamento.<br />

Uma das ferramentas mais utilizadas para a comparação de seqüências de DNA com<br />

os bancos de dados genômicos é o BLAST (Basic Local Alignment Search Tool) [6]. O<br />

BLAST é na verdade uma família de ferramentas para análises de DNA e proteínas e não<br />

um único programa.<br />

Uma outra família de ferramentas bastante utilizada, que também utiliza heurísticas,<br />

é o FAST [59], para comparações globais.<br />

Se os algoritmos de comparação baseados em programação puderem ser acelerados de<br />

6


modo a se tornar viável sua utilização, respostas ótimas poderão ser obtidas, uma vez que<br />

as soluções baseadas em heurísticas podem ocultar importantes relacionamentos entre as<br />

seqüências comparadas.<br />

Dentre as alternativas que vêm sendo pesquisadas estão a utilização de técnicas de<br />

computação paralela, que se baseia na cooperação de um conjunto de processadores que<br />

dividem a carga computacional e a construção de hardware específico e dedicado, dessa<br />

forma, mais otimizado e veloz, para a solução desse problema.<br />

Muitos esforços nas áreas comercial e acadêmica já foram feitos para utilizarem hardware<br />

específico com o objetivo de acelerar as pesquisas nos bancos de dados.<br />

Nesta dissertação é proposto um sistema baseado em hardware, chamado de ASIC-<br />

GENE (Acelerador Sistólico para Comparações Genéticas), e que utiliza um dispositivo<br />

reconfigurável conhecido como FPGA. Uma estrutura sistólica linear unidirecional é apresentada<br />

para acelerar o processo da comparação entre seqüências. Essa estrutura possui<br />

inúmeros pequenos processadores dedicados (chamados de elementos de processamento)<br />

que efetuam operações em paralelo, obtendo um significativo ganho de performance em<br />

relação à computação seqüencial.<br />

1.2 Revisão Bibliográfica<br />

Em 1985, Lipton e Lopresti [43] mostraram que o paralelismo existente no algoritmo de<br />

Smith-Waterman poderia ser mapeado em uma estrutura linear sistólica bidirecional. Na<br />

estrutura obtida, cada elemento de processamento (PE) do vetor sistólico era responsável<br />

pelo cálculo de uma das diagonais da matriz de similaridade, com a diagonal principal<br />

sendo processada no centro desse vetor (figura 1.2).<br />

Figura 1.2: Mapeamento do cálculo da matriz de similaridade em uma estrutura sistólica<br />

bidirecional.<br />

As seqüências a serem comparadas entravam em lados opostos do vetor e eram deslocadas<br />

a cada ciclo de relógio de modo a atravessar a estrutura linear. Dessa forma, o<br />

primeiro elemento das duas seqüências se encontravam no centro do vetor, quando era calculado<br />

o primeiro valor da matriz de similaridade. A cada ciclo de relógio, as seqüências<br />

se deslocavam em sentidos opostos e mais valores iam sendo calculados.<br />

7


Se as duas seqüências a serem comparadas possuíssem comprimentos iguais a n e<br />

m, a estrutura linear proposta deveria ter um comprimento de n + m − 1 elementos de<br />

processamento. Entretanto, a complexidade de tempo do algoritmo caiu de O(n × m)<br />

para O(n + m), ou seja, uma complexidade linear.<br />

Para o cálculo de cada elemento da matriz de similaridade, foi sugerido um esquema<br />

de pontuação sem valores negativos e que penalizava mais o alinhamento de caracteres<br />

diferentes das duas seqüências do que o alinhamento de um caracter de uma das duas<br />

seqüências com um espaço (gap). A pontuação proposta seguia a seguinte regra:<br />

t j<br />

. . .<br />

a b<br />

s i . . . c d<br />

⎧<br />

⎪⎨<br />

d = min<br />

⎪⎩<br />

b + 1<br />

c + 1<br />

a se s i = t j<br />

a + 2 se s i ≠ t j<br />

Com esse esquema de pontuação, foi demonstrado que o valor calculado para d seria<br />

igual ao de a ou então igual a a + 2. Com isso, apenas um bit indicaria essa diferença.<br />

Por esse motivo, essa implementação não armazenava os valores calculados da matriz de<br />

similaridade e conforme os dados iam saindo em uma das pontas do vetor, um contador<br />

previamente carregado ia sendo incrementado ou decrementado de acordo com os bits<br />

gerados. No final do processo, o último valor do contador indicava quão próximas eram<br />

as seqüências comparadas. Se o valor fosse baixo, indicava que as seqüências eram bem<br />

parecidas, com um valor igual a zero no caso das seqüências serem idênticas. Valores altos<br />

no contador indicavam que as seqüências eram bem diferentes.<br />

Com essa implementação não era possível obter nenhum alinhamento entre as duas<br />

seqüências e o resultado obtido era meramente um indicador de proximidade entre elas.<br />

Foi observado que os diversos artigos definem dois conceitos: comparação de seqüências<br />

e alinhamento de seqüências. Na comparação, o resultado obtido é simplesmente um<br />

escore que indica se as seqüências comparadas são próximas ou não. No alinhamento é<br />

que se consegue obter quais trechos de uma seqüência são similares ao da outra seqüência<br />

comparada.<br />

Baseadas nessa abordagem, foram propostas várias implementações. Em 1992, Hoang<br />

[31] descreve uma solução bastante similar, utilizando a arquitetura SPLASH [22],<br />

uma matriz lógica linear programável desenvolvida pelo Supercomputer Researh Center<br />

(SRC), que utilizava 32 FPGAs XC3090 da Xilinx [75]. Nessa solução era possível recuperar<br />

pelo menos um alinhamento, embora o esquema de pontuação utilizado foi o proposto<br />

por Lipton e Lopresti.<br />

Em 1993, Hoang [52] sugere uma nova solução utilizando uma arquitetura sistólica<br />

unidirecional, agora baseada no SPLASH 2 [9], uma evolução do sistema anterior. As<br />

duas seqüências eram colocadas em um único vetor e deslocadas para dentro da estrutura<br />

sistólica. Uma marca em cada posição desse vetor indicava quais bases faziam parte da<br />

seqüência de consulta e quais bases eram do banco de dados. Nessa solução, não foram<br />

8


dados detalhes sobre a recuperação de alinhamentos e pela estrutura da célula, apenas o<br />

cálculo de um escore de similaridade (comparação de seqüências) era feito.<br />

Utilizando o acelerador SAMBA [38] (Systolic Accelerator for Molecular Biological<br />

Applications), Lavenier propõe, em 1998, uma nova abordagem para o problema, mas<br />

ainda utilizando uma arquitetura sistólica, pela própria estrutura do SAMBA.<br />

Uma nova implementação da solução de Hoang ocorreu em 2002, utilizando tecnologia<br />

mais moderna, como a família Virtex de FPGAs da Xilinx [25]. A solução de Hoang<br />

também deu origem ao HokieGene [60], um sistema reconfigurável em tempo de execução<br />

baseado na placa Osiris [36] desenvolvida pelo Information Sciences Institute.<br />

Uma solução bastante similar à proposta nessa dissertação foi apresentada por Yamaguchi,<br />

Maruyama e Konagaya [76] em 2002. Nela uma placa PCI contendo uma FPGA<br />

XCV2000E da Xilinx, que contém 43200 células lógicas, foi utilizada, sendo possível a<br />

implementação de 144 elementos de processamento. Cada elemento de processamento<br />

leva quatro ciclos de relógio para gerar seu resultado. Nessa solução não é dito nada sobre<br />

a utilização de uma arquitetura sistólica. A comparação é dividida em vários pedaços<br />

devido às limitações da memória interna da FPGA.<br />

Com algumas modificações, mas ainda baseada na solução de Hoang de 1993, uma nova<br />

proposta é feita por Yu, Kwong, Lee e Leong [78] em 2003. Essa implementação também<br />

utiliza FPGAs da família Virtex da Xilinx, mais especificamente XCV1000E, com 27648<br />

células lógicas.<br />

Algumas soluções utilizando VLSI também foram propostas, como BioScan [73] em<br />

1991, KESTREL [30] em 1996 e as Proclets de Yang [77] em 2002. Essa última utiliza uma<br />

unidade de processamento (chamada de Proclet) para cada célula da matriz de similaridade<br />

e, dessa forma, torna-se muito onerosa, dada as dimensões que a matriz pode atingir.<br />

Dentre as arquiteturas dedicadas, além das já citadas SPLASH, Osiris e SAMBA,<br />

destacam-se o GeneMatcher2 [57] da Paracel [56] que usa um processador ASIC otimizado<br />

para essa tarefa, e o DeCypher [68] da TimeLogic [67] que utiliza FPGAs.<br />

1.3 Objetivos<br />

As soluções analisadas com maior interesse foram as que utilizaram FPGAs. A grande<br />

maioria delas foi baseada nas propostas de Lipton e Lopresti e de Hoang. Nessas abordagens<br />

foi utilizado um esquema de pontuação que, embora simplifique o hardware, penaliza<br />

mais a substituição do que a inserção ou remoção de uma base em uma das seqüências<br />

(ocorrência de espaços). Outro fato observado é que o resultado é simplesmente um escore<br />

que indica a proximidade entre as seqüências comparadas. Quanto menor o escore, maior<br />

a similaridade entre elas.<br />

Nas soluções não baseadas nessas propostas, um hardware dedicado de maior envergadura<br />

foi utilizado como suporte. A exceção é a solução apresentada por Yamaguchi,<br />

9


Maruyama e Konagaya que utilizada placas PCIs de “prateleira”. Entretanto, não são<br />

fornecidos maiores detalhes sobre a implementação feita, de forma que ela pudesse ser<br />

reproduzida.<br />

Dessa forma, até onde se pôde perceber, o trabalho proposto nesta dissertação é inédito,<br />

pois detalha todo o fluxo dos dados dentro da arquitetura sistólica e utiliza um esquema de<br />

pontuação mais voltado para os aspectos biológicos do problema e não com simplificações<br />

do circuito. Além disso, a matriz de similaridade é armazenada e permite a recuperação<br />

de todos os alinhamentos entre as duas seqüências comparadas.<br />

Assim, os objetivos desta dissertação são:<br />

• Propor, implementar e validar uma solução paralela baseada em hardware para o<br />

problema de comparar seqüências utilizando o algoritmo de Smith-Waterman [66];<br />

• Realizar comparações de desempenho com outras implementações do algoritmo,<br />

seqüenciais e paralelas.<br />

1.4 Organização da Dissertação<br />

No capítulo 2 são apresentados os conceitos básicos em Biologia Molecular, sendo<br />

descritos os algoritmos de comparação de seqüências baseados em programação dinâmica.<br />

No capítulo 3, são revistas as arquiteturas sistólicas e as arquiteturas reconfiguráveis, além<br />

de outros conceitos a serem utilizados. A descrição da solução proposta é apresentada no<br />

capítulo 4. Os resultados dos experimentos realizados e análises desses resultados são<br />

apresentados no capítulo 5. Finalmente, no capítulo 6 são apresentadas as conclusões<br />

deste trabalho e propostas novas direções de pesquisa a partir dele.<br />

10


Capítulo 2<br />

FUNDAMENTAÇÃO TEÓRICA<br />

2.1 Biologia Molecular<br />

Um dos pontos fundamentais da Teoria Atômica proposta por John Dalton [15] era que<br />

a matéria é constituída por unidades indivisíveis, os átomos. Estes, unidos uns aos outros,<br />

compõem as moléculas, que juntas formam uma célula. Segundo a teoria celular [7][8],<br />

formulada em 1839, por Schleiden e Schwann, todo ser vivo é formado por células. De<br />

forma simplista, a vida resulta de um complexo conjunto de reações bioquímicas que ocorrem<br />

nas células. Duas estruturas se destacam nesta química da vida: os ácidos nucléicos<br />

e as proteínas.<br />

A Biologia Molecular é a ciência onde se visa compreender a estrutura e função<br />

dos ácidos nucléicos e proteínas, e como estes participam nos intrincados processos responsáveis<br />

pela origem e conservação da vida citeSetubal.<br />

2.1.1 Ácidos Nucléicos<br />

A história da descoberta dos ácidos nucléicos remonta aos fins do século XIX, quando F.<br />

Miescher (1868), em um importante trabalho de citoquímica, isolou e analisou o núcleo das<br />

células. No entanto, foi Richard Altmann que, em 1889, atribuiu a designação de ácidos<br />

nucléicos, uma vez que foram primeiramente identificados no núcleo e porque manifestam<br />

propriedades ácidas.<br />

Os ácidos nucléicos estão presentes em todos os seres vivos, sejam eles simples ou<br />

complexos, e contêm as informações necessárias para a síntese de todas as proteínas que<br />

cada organismo é capaz de produzir [59]. São moléculas orgânicas gigantes formadas por<br />

uma cadeia de unidades menores chamadas nucleotídeos. Existem dois tipos principais: o<br />

ácido ribonucléico (RNA) e o ácido desoxirribonucléico (DNA).<br />

Cada nucleotídeo do ácido nucléico consiste de três partes básicas: um grupo fosfato,<br />

um açúcar e uma base nitrogenada (anel heterocíclico de átomos de carbono e nitrogênio).<br />

A base nitrogenada, de acordo com sua estrutura química, pode ser púrica ou pirimídica.<br />

Adenina (A) e guanina (G) são bases púricas enquanto citosina (C), timina (T)<br />

e uracila (U) são bases pirimídicas.<br />

11


As purinas são constituídas de dois anéis fundidos de 5 e 6 átomos e as pirimidinas<br />

de um único anel de 6 átomos. Uracil e Timina são moléculas bastante relacionadas,<br />

diferindo apenas pelo grupo metila encontrado no átomo C5 do anel pirimídico da Timina<br />

(figura 2.1). É a presença do nitrogênio que dá a essas moléculas o seu caráter básico.<br />

Apenas quatro tipos diferentes de bases são encontrados em um dado polímero de<br />

ácido nucléico, sendo duas purinas e duas pirimidinas. No DNA as bases constituintes são<br />

A, G, C, e T, enquanto que no RNA as bases são A, G, C e U.<br />

Figura 2.1: Bases Nitrogenadas.<br />

A molécula de açúcar, também chamada de pentose por ser composta de 5 átomos<br />

de carbono, pode ser de dois tipos, desoxirribose e ribose. Diferem uma da outra pela<br />

presença ou ausência do grupo hidroxila no C2’ (figura 2.2). É baseado nessa característica<br />

que os ácidos nucléicos recebem o nome RNA (ribose) ou DNA (desoxirribose).<br />

Figura 2.2: Tipos de Açúcares.<br />

A pentose é o elo de ligação entre a base e o grupo fosfato. De um lado, o Nitrogênio<br />

9 das purinas ou o Nitrogênio 1 das pirimidinas liga-se ao C1’ da pentose e, de outro lado,<br />

o grupo carboxila do átomo de C5’ da pentose participa da ligação éster com o grupo<br />

fosfato.<br />

12


2.1.1.1 DNA<br />

Segundo o modelo descoberto por Watson-Crick [72], o DNA é uma longa molécula,<br />

constituída por duas cadeias de nucleotídeos (um grupo fosfato, um açúcar e uma base<br />

nitrogenada), chamadas fitas, enroladas em torno de seu próprio eixo, como se fosse uma<br />

escada do tipo caracol (figura 2.3). A ligação entre as fitas é feita por pontes de hidrogênio,<br />

que são ligações fracas, isto é, que se rompem com facilidade. As pontes de hidrogênio<br />

unem duas bases nitrogenadas e são decorrentes de propriedades químicas entre uma base<br />

púrica e uma pirimídica, formando os chamados pares de bases (bp).<br />

Figura 2.3: A estrutura de uma molécula de DNA, formada por uma dupla fita. (a) Forma<br />

helicoidal da dupla cadeia. (b) Forma esquemática da dupla cadeia, onde podemos visualizar a<br />

ligação entre as moléculas de açúcar (S) e de fosfato (P), em cada uma das fitas, e o emparelhamento<br />

das bases Adenina/Timina e Citosina/Guanina, entre as duas fitas.<br />

O pareamento das bases de cada fita se dá de maneira padronizada, sempre uma<br />

purina com uma pirimidina, especificamente: adenina (A) com timina (T) e citosina (C)<br />

com guanina (G).<br />

Como cada ligação ocorre entre o carbono 3’ de um composto, o fosfato e o carbono<br />

5’ do próximo composto, diz-se que o DNA possui uma orientação que, por convenção,<br />

inicia-se na extremidade 5’ e termina na 3’, denominada direção canônica [64]. Assim,<br />

uma seqüência de nucleotídeos em uma fita corresponde à seqüência dos nucleotídeos<br />

complementares da outra fita, por causa do emparelhamento das bases. Dizemos que as<br />

duas fitas são complementares.<br />

Além disso, deve-se notar que as duas fitas possuem sentidos opostos. Uma fita começa<br />

em 5’ e termina em 3’, que é emparelhada com a outra, que começa em 3’ e termina em 5’.<br />

13


Por convenção, a fita de sentido 5’ → 3’ é colocada acima, como mostrado na figura 2.4.<br />

Figura 2.4: Dupla fita de DNA, observando-se o pareamento das bases A-T e C-G.<br />

A seqüência do DNA é determinada pela ordem das bases nitrogenadas ao longo de<br />

cada uma das fitas, já que o fosfato (P) e o açúcar (S) são idênticos em todos os nucleotídeos.<br />

Daí os pares de bases (bp) serem usados como unidades de comprimento para<br />

uma molécula de DNA. O tamanho do DNA varia para cada organismo, podendo ser de<br />

alguns milhões de bases, como no caso de uma bactéria, até de alguns bilhões de bases,<br />

no caso dos mamíferos.<br />

O DNA codifica todas as proteínas que as células devem sintetizar, o que garante<br />

a sobrevivência da espécie. Portanto, a principal função do DNA é armazenar toda a<br />

informação genética de um organismo. A conservação e transmissão dessas informações<br />

são realizadas pelos processos de duplicação e transcrição, respectivamente.<br />

2.1.1.2 RNA<br />

As moléculas de RNA possuem composição química e estrutural bastante similares às<br />

de DNA. As diferenças químicas estão no fato de o nucleotídeo ser formado pelo açúcar<br />

ribose e pela substituição da timina (T) pela uracila (U). As outras bases nitrogenadas<br />

são todas as mesmas que compõem o DNA: citosina (C), guanina (G) e adenina (A).<br />

Estruturalmente, enquanto o DNA apresenta-se como uma longa hélice dupla com uma<br />

estrutura secundária regular e simples, os RNAs são, geralmente, moléculas de fita única<br />

bem menores que o DNA, apresentando uma enorme diversidade de estruturas secundárias,<br />

com certas regiões podendo formar até mesmo uma dupla hélice.<br />

A estabilidade e regularidade estrutural da molécula de DNA, deve-se principalmente<br />

ao fato dos anéis de desoxirribose não possuírem grupos hidroxila no C2’. Os grupos<br />

hidroxila tanto do C2’ como C3’ são muito reativos e podem participar de uma série de<br />

ligações pouco usuais, permitindo uma variedade enorme de conformações para a molécula<br />

de ácido nucléico. Tal variedade, não seria uma característica desejável para uma molécula<br />

que tem armazenado e transmitido a informação genética durante estes milhões de anos<br />

de evolução. O exercício de tal função exige estabilidade e regularidade.<br />

Já o RNA, constituído de riboses é, por isso mesmo, muito mais reativo e flexível.<br />

Além disto, o fato de ser fita simples permite um emparelhamento intramolecular de<br />

bases, gerando estruturas bastante complexas. Ao adquirir diferentes conformações numa<br />

estrutura tridimensional, as moléculas de RNA podem, inclusive, apresentar sítios ativos<br />

14


que catalisem reações químicas da mesma forma que as enzimas protéicas.<br />

É a grande flexibilidade dos RNAs que lhes permite executar uma atividade fundamental<br />

na célula, qual seja, a de interpretar o código contido na linguagem de nucleotídios<br />

e decodificá-lo para a linguagem de aminoácidos. A molécula de RNA é o intermediário<br />

no fluxo de informações dentro da célula, do DNA às proteínas. Assim, existem diferentes<br />

tipos de RNA, tais como o RNA mensageiro (RNAm), o RNA ribossômico (RNAr) e<br />

o RNA transportador (RNAt), responsáveis por diversas funções vitais na realização da<br />

síntese de proteínas.<br />

A tabela 2.1 apresenta as diferenças fundamentais entre o DNA e o RNA.<br />

2.1.2 Aminoácidos<br />

De um modo geral, cada composto orgânico pertence a um determinado grupo. Entretanto,<br />

existem compostos que pertencem simultaneamente a dois ou mais grupos, ou<br />

seja, são de função mista. A figura 2.5 mostra alguns desses grupos.<br />

Figura 2.5: Exemplo de alguns grupos orgânicos.<br />

Os aminoácidos são compostos orgânicos de função mista e que apresentam em suas<br />

moléculas um grupo ácido (-COOH) e um grupo amina (-NH2), além de um radical -R, que<br />

vai ser responsável pela diferenciação entre os diversos tipos existentes (figura 2.6). Graças<br />

à presença de grupamentos derivados de ácidos carboxílicos e de aminas, os aminoácidos<br />

são dotados de propriedades de ácidos e bases. Esse duplo caráter é de vital importância<br />

para a compreensão do comportamento e das funções das proteínas e, por conseguinte, da<br />

matéria viva.<br />

Todas as proteínas existentes nos seres vivos, desde os vírus até os seres humanos, são<br />

constituídas por combinações de apenas 20 aminoácidos. Esses blocos constituintes da<br />

Tabela 2.1: Principais diferenças entre o DNA e o RNA.<br />

DNA<br />

RNA<br />

Nucleotídeo fosfato, desoxirribose, fosfato, ribose,<br />

base nitrogenada base nitrogenada<br />

Bases Nitrogenadas A, T, C e G A, U, C e G<br />

Estrutura duas cadeias normalmente,<br />

em estrutura helicoidal cadeia simples<br />

Função única varia de acordo com o tipo<br />

15


Figura 2.6: Estrutura e exemplos de alguns aminoácidos.<br />

vida se unem entre si para formar longas cadeias e moléculas complexas que configuram a<br />

estrutura de todos os organismos vivos. A tabela 2.2 mostra os aminoácidos encontrados<br />

na natureza, bem como suas abreviações e códigos utilizados.<br />

Os aminoácidos são classificados em essenciais e não-essenciais. Os essenciais, ou<br />

indispensáveis, são aqueles que o organismo humano não consegue sintetizar. Desse modo,<br />

eles devem ser obrigatoriamente ingeridos através de alimentos. Os aminoácidos nãoessenciais,<br />

ou dispensáveis, são aqueles que o organismo humano consegue sintetizar a<br />

partir dos alimentos ingeridos.<br />

São 8 os aminoácidos essenciais, a saber: leucina, isoleucina, valina, triptofano, metionina,<br />

fenilalanina, treonina e lisina (a histidina é um aminoácido essencial na infância,<br />

mas não na idade adulta).<br />

2.1.3 Proteínas<br />

As proteínas são compostos orgânicos de estrutura complexa e massa molecular elevada<br />

(entre 15.000 e 20.000.000) e são sintetizadas pelos organismos vivos através da condensação<br />

de um número grande de moléculas de aminoácidos, por intermédio de ligações<br />

denominadas peptídicas, que derivam da reação do grupo amina de um dos aminoácidos<br />

com o grupo carboxila de outro (figura 2.7). Pelo fato de uma molécula de água ser liberada<br />

como resultado dessa reação, cada aminoácido, após a união, passa a ser um resíduo<br />

do aminoácido original.<br />

Figura 2.7: União de dois aminoácidos por uma ligação peptídica.<br />

Para que as células funcionem são necessárias a realização de uma enorme quantidade<br />

de reações químicas que se processam em seu interior. As enzimas, proteínas especiais,<br />

regulam a atividade celular controlando e catalisando essas reações químicas.<br />

Além disso, as proteínas participam nos processos de duplicação, transcrição e reparo.<br />

A vida e a reprodução dependem da manutenção desses processos e da disponibilidade de<br />

16


Tabela 2.2: Os 20 diferentes tipos de aminoácidos encontrados na natureza.<br />

Aminoácido Abreviação Código<br />

Alanina Ala A<br />

Asparagina ou Aspartato Asx B<br />

Cisteína Cis ou Cys B<br />

Aspartato (Ácido aspártico) Asp D<br />

Glutamato (Ácido glutâmico) Glu E<br />

Fenilalanina Fen ou Phe F<br />

Glicina Gli ou Gly G<br />

Histidina His H<br />

Isoleucina Ile I<br />

Lisina Lis ou Lys K<br />

Leucina Leu L<br />

Metionina Met M<br />

Asparagina Asn N<br />

Prolina Pro P<br />

Glutamina (Glutamida) Gln Q<br />

Arginina Arg R<br />

Serina Ser S<br />

Treonina Ter ou Thr T<br />

Valina Val V<br />

Triptofano (Triptofana) Trp W<br />

Tirosina Tir ou Tyr Y<br />

Glutamina ou Glutamato Glx Z<br />

17


energia e dos componentes necessários para isso. Dessa forma, a síntese das proteínas é<br />

fundamental para o crescimento, o desenvolvimento e a manutenção celular.<br />

Para a formação de uma proteína é preciso uma informação que irá ditar a seqüência<br />

em que os aminoácidos devem ser unidos. Essas informações estão inscritas nas moléculas<br />

do DNA.<br />

Embora a seqüência de aminoácidos determine a estrutura da proteína, conhecida<br />

como estrutura primária, não é possível predizer com precisão a conformação espacial<br />

adotada por uma determinada proteína, apenas por esta seqüência. As interações moleculares<br />

entre os aminoácidos fazem com que a cadeia protéica assuma uma estrutura<br />

secundária. Podemos ter ainda as estruturas terciárias, resultado da estrutura secundária<br />

empacotadas em um nível mais global, e as estruturas quaternárias, quando<br />

um grupo de proteínas diferentes são empacotadas juntas.<br />

É possível também classificar proteínas com base em sua função. Elas podem ser divididas<br />

em dois grupos: proteínas estruturais e proteínas biologicamente ativas. Algumas<br />

proteínas, entretanto, podem pertencer aos dois grupos. A maioria das proteínas estruturais<br />

é composta por cadeias alongadas e têm como função compor estruturas de órgãos,<br />

tecidos, etc. Dois bons exemplos, nos animais, são o colágeno (ossos, tendões, pele e<br />

ligamentos) e a queratina (unhas, cabelos, penas e bicos). A maioria das proteínas biologicamente<br />

ativas tem forma globular e são encarregadas de executar ou controlar a maior<br />

parte das atividades dentro do organismo. Exemplos são as enzimas que aceleram reações<br />

químicas, os hormônios protéicos (que atuam como mensageiros químicos), as proteínas de<br />

transporte (como as lipoproteínas, que podem carregar o colesterol) e as imunoglobulinas<br />

(ou anticorpos), que protegem o corpo de microorganismos invasores [64].<br />

2.1.4 Genes<br />

Nas células dos organismos, cada molécula de DNA forma um cromossomo. O<br />

número de cromossomos é característico da espécie. Por exemplo, nas células dos seres<br />

humanos existem 23 pares de cromossomos.<br />

Cada molécula de DNA contém diversos genes, que são as unidades físicas e funcionais<br />

básicas da hereditariedade [2]. Um gene é uma seqüência específica de bases de<br />

uma molécula de DNA que contém a informação necessária para sintetizar proteínas ou<br />

RNA [2].<br />

Todos os genes estão dispostos linearmente ao longo dos cromossomos na forma de trechos<br />

contíguos. Mas, entre os genes, existem trechos, chamados DNA não-codificante<br />

que não possuem função codificadora, pelo conhecimento atual da ciência. Nos procariontes,<br />

organismos que não possuem núcleo organizado, os cromossomos estão quase totalmente<br />

cobertos por genes, mas, nos eucariontes, organismos com núcleo bem definido,<br />

estima-se que cerca de 90% do cromossomo seja DNA não-codificante [64].<br />

O conjunto completo de cromossomos de um organismo compreende o seu genoma,<br />

18


que engloba todas as informações necessárias para originar e manter a vida. A figura 2.8<br />

mostra o esquema dos genes dentro dos cromossomos e destes dentro do genoma. Estimase<br />

que o genoma humano possua aproximadamente 30.000 genes [2].<br />

Figura 2.8: Visão esquemática dos genes, cromossomos e genoma.<br />

Geralmente, cada gene em uma molécula de DNA corresponde a um tipo diferente<br />

de proteína. A informação genética contida nos genes é transmitida por triplas de nucleotídeos,<br />

chamadas códons. Cada códon representa um aminoácido na proteína e essa<br />

correspondência é chamada de código genético (figura 2.9).<br />

Figura 2.9: Código genético.<br />

A combinação das quatro letras genéticas (A,T,C,G) três a três permite obter 64 trincas<br />

diferentes. Dessas 64 trincas possíveis, apenas 61 correspondem a aminoácidos; as três<br />

restantes são utilizadas para indicar onde termina um mensagem genética (STOP). Em<br />

geral, o início de um gene é indicado pelo códon AUG.<br />

Como existem apenas 20 tipos diferentes de aminoácidos nas proteínas do seres vivos,<br />

alguns aminoácidos são codificados por mais de uma trinca de nucleotídeos. Por isso,<br />

diz-se que o código genético é degenerado.<br />

2.1.5 Genética Molecular<br />

O material responsável pelo comando e coordenação de toda a atividade celular e<br />

pelas divisões celulares e transmissões das características hereditárias está representado<br />

19


Figura 2.10: Duplicação do DNA.<br />

nas células pelos cromossomos. A conservação e a transmissão da informação genética<br />

ocorrem devido ao processo de duplicação do DNA, que acontece durante a divisão de<br />

uma célula, produzindo duas células filhas exatamente iguais.<br />

Na duplicação, as fitas do DNA se separam e cada uma serve de molde para a formação<br />

de uma fita complementar através do pareamento de bases. No final do processo haverá<br />

duas moléculas de DNA, cada uma constituída por uma fita original e outra complementar<br />

recém-fabricada (figura 2.10). É geralmente durante este processo que ocorrem as variações<br />

genéticas decorrentes de mutações, por exemplo, substituições, remoções ou inserções de<br />

bases.<br />

2.1.6 Síntese Protéica<br />

A expressão da informação genética ocorre na forma de proteínas, segundo o Dogma<br />

Central da Biologia Molecular, que preconiza que os genes são perpetuados como<br />

seqüências de ácidos nucléicos e, a partir destes, expressos na forma de proteínas. Duas<br />

fases compõem o processo de síntese de proteínas: transcrição e tradução.<br />

Na primeira etapa da síntese, ocorre a transcrição da informação depositada no<br />

DNA para uma cópia feita a partir de ribonucleotídeo. Assim, obtém-se uma molécula<br />

alongada de RNA com a mesma seqüência de nucleotídeo observada no DNA, com exceção<br />

da base timina substituída pela uracila. Esta cópia de DNA recebe o nome de RNA<br />

mensageiro (RNAm). O RNAm carrega a informação codificada para os ribossomos,<br />

que são estruturas celulares responsáveis por processar o código genético e sintetizar as<br />

proteínas [2].<br />

Terminada a transcrição do DNA, o RNAm sai do núcleo para o citoplasma rumo ao<br />

ribossomo, levando a seqüência de nucleotídeos que permitirá a formação das proteínas.<br />

Para que isso ocorra é necessário a tradução da seqüência de nucleotídeos do RNAm em<br />

seqüência de aminoácidos (figura 2.11).<br />

20


Figura 2.11: Representação esquemática da transcrição e tradução.<br />

Todas as células contêm um conjunto de RNA, os RNA transportadores (RNAt), que<br />

através da ligação de uma de suas extremidades a um códon, permite o alinhamento dos<br />

aminoácidos de acordo com a seqüência de nucleotídeos do RNAm.<br />

Um RNAt é responsável pelo transporte de um dos vinte aminoácidos utilizados na<br />

síntese de proteínas. Cada um dos aminoácidos tem pelo menos um tipo de RNAt a<br />

ele designado. O aminoácido é ligado ao RNAt que possui um anticódon (seqüência<br />

de três nucleotídeos que é complementar aos três nucleotídeos do códon que especifica o<br />

aminoácido na molécula de RNAm) correto, gerando uma molécula de aminoacil-RNAt.<br />

Através do pareamento códon-anticódon, o aminoácido é inserido em uma cadeia crescente<br />

de proteína, de acordo com o que está determinado na seqüência de nucleotídeo do RNAm.<br />

Com uma extremidade ligada a um aminoácido e a outra pareada a um códon, o RNAt<br />

converte a seqüência de nucleotídeo na seqüência de aminoácidos (figura 2.12). Apenas a<br />

molécula de RNAt, e não os aminoácidos a ela ligados, determina onde o aminoácido é<br />

adicionado durante a síntese de proteína.<br />

Figura 2.12: Detalhamento do processo de tradução.<br />

21


2.2 Algoritmos para Comparação de Seqüências Baseados<br />

em Programação Dinâmica<br />

A comparação de seqüências é a operação primitiva mais importante em Bioinformática,<br />

servindo como base para muitas outras manipulações complexas e é vastamente utilizada<br />

nos projetos de seqüenciamento.<br />

A comparação de seqüências consiste em duas partes: encontrar uma medida que indique<br />

a similaridade entre as seqüências, e obter uma forma de visualizar esta similaridade.<br />

A similaridade é uma métrica que expressa quantitativamente quão parecidas são duas<br />

seqüências. Já a visualização é feita por um alinhamento, que é um método de escrever<br />

uma seqüência acima da outra para tornar explícitas as correspondências entre caracteres<br />

ou regiões de caracteres similares das duas seqüências.<br />

O melhor alinhamento, ou<br />

alinhamento ótimo, é aquele que apresenta o máximo de regiões de similaridade [64].<br />

2.2.1 Alinhamento de seqüências<br />

Quando seqüências são comparadas, diversos termos podem ser utilizados para expressar<br />

o resultado encontrado. Identidade, similaridade e homologia de seqüências são<br />

os mais importantes, e embora sejam freqüentemente utilizados de forma intercambiável,<br />

seus significados são diferentes.<br />

A identidade entre seqüências se refere à ocorrência exata dos mesmos resíduos nas<br />

mesmas posições das seqüências alinhadas. A similaridade considera a possibilidade de<br />

ocorrência de mutações, sendo significativa quando estas são pontuadas de acordo com<br />

a probabilidade que têm de ocorrerem, sob um ponto de vista biológico. A homologia<br />

indica a existência de um relacionamento evolucionário entre as seqüências. A diferença<br />

entre os dois últimos termos é que a similaridade se refere à presença de locais idênticos<br />

ou similares nas seqüências, enquanto a homologia reflete uma afirmação mais forte, a de<br />

que as seqüências possuem um ancestral comum.<br />

Comparar seqüências depende da computação de um alinhamento entre elas. Para<br />

isso, é utilizado um esquema de pontuação do alinhamento. Cada coluna do alinhamento<br />

recebe um certo valor dependendo do seu conteúdo. A soma desses valores consiste na<br />

pontuação do alinhamento.<br />

Assim, as seqüências a serem comparadas são emparelhadas, ou seja, posicionadas uma<br />

acima da outra, de modos arbitrários e para cada um desses emparelhamentos é calculado<br />

um valor de acordo com certos critérios. O melhor alinhamento dentre todos os possíveis<br />

será aquele que possuir a maior pontuação.<br />

máximo, ambos serão considerados ótimos.<br />

Se dois alinhamentos resultarem no valor<br />

Um alinhamento de seqüências deve permitir introdução de espaços (gaps) em locais arbitrários<br />

das seqüências para compensar inserções ou remoções de bases de uma seqüência<br />

em relação a outra. A inclusão de espaços mantém, em registro, seqüências obviamente<br />

22


similares, o que não seria possível com um alinhamento direto sem eles. Assim, os espaços<br />

nos permitem lidar com contingências tais como duplicações internas, repetições, crossingover<br />

desigual e outras delinqüências genéticas. Não é permitido que um espaço em uma<br />

seqüência seja alinhado com um espaço na outra seqüência.<br />

Cada coluna do alinhamento recebe um certo valor dependendo do seu conteúdo. A<br />

soma desses valores resulta na pontuação do alinhamento. Um esquema de pontuação<br />

muito utilizado define um valor igual a +1 para colunas com caracteres coincidentes (matches)<br />

e −1 para colunas com caracteres divergentes (mismatches). Para impedir o acúmulo<br />

de muitos espaços em um alinhamento, uma quantidade fixa deve ser deduzida do valor<br />

acumulado a cada espaço introduzido. Assim, os espaços possuem pontuação negativa.<br />

Esse esquema de pontuação sugere o valor −2 para cada espaço inserido. Pode ainda ser<br />

definida uma penalidade mais suave para a extensão do espaço (espaços sucessivos).<br />

Por exemplo, considerando duas seqüências x = CCT AGA e y = CT AT GCAC, um<br />

possível alinhamento entre elas é mostrado na figura 2.13 e resultaria em uma pontuação<br />

(escore) igual a −5.<br />

Figura 2.13: Pontuação de um possível alinhamento entre CCTAGA e CTATGCAC.<br />

Nas comparações de seqüências de DNA, utiliza-se uma matriz unitária onde somente<br />

caracteres idênticos recebem uma pontuação positiva. No caso de se comparar<br />

seqüências protéicas, utilizam-se matrizes de substituição. Aminoácidos relativamente<br />

semelhantes recebem pontuação positiva e não semelhantes recebem pontuação negativa.<br />

Uma matriz de comparação para proteínas, amplamente utilizada nos últimos anos, foi a<br />

matriz PAM ( Point Accepted Mutation), construída por Dayhoff [16].<br />

Para construí-la, ele observou todas as substituições de aminoácidos verificadas em<br />

alinhamentos de um amplo conjunto de proteínas intimamente relacionadas, as quais<br />

tinham sofrido uma certa divergência evolucionária. A cada substituição possível de um<br />

resíduo foi dada uma pontuação que reflete a probabilidade de estar relacionado ao resíduo<br />

correspondente da seqüência em consulta. A pontuação do alinhamento é a soma das<br />

pontuações individuais e mede a quantidade de alterações evolutivas numa seqüência. Em<br />

média, 1,0 unidade PAM corresponde a alterações em 1% dos aminoácidos numa seqüência<br />

protéica.<br />

Um método alternativo, baseado nas matrizes BLOSUM (Blocks Substitution Matrix)<br />

[27] tem se mostrado superior à matriz PAM para detectar os parentescos biológicos<br />

entre seqüências moderadamente divergentes. No caso da matriz BLOSUM62, por exem-<br />

23


plo, o máximo de identidade compartilhado por duas seqüências é 62% e os scores são<br />

derivados da comparação de blocos de alinhamentos localizados nas proteínas relacionadas.<br />

Dependendo do tamanho das seqüências que estão sendo comparadas, matrizes de<br />

um tipo ou de outro são mais apropriadas.<br />

2.2.2 Algoritmos baseados em programação dinâmica<br />

Waterman mostrou que encontrar alinhamentos é um problema difícil, já que o número<br />

de alinhamentos possíveis é exponencial, dado aproximadamente pela fórmula [71]<br />

onde n representa o tamanho das seqüências.<br />

A n = (1 + √ 2) 2n+1√ n, (2.1)<br />

2.2.2.1 Comparação global<br />

Em 1970, Needleman e Wunsch [51] apresentaram o primeiro algoritmo de comparação<br />

de seqüências capaz de determinar o melhor alinhamento entre duas seqüências sem enumerar<br />

todas as soluções possíveis. A solução foi baseada em técnicas de programação<br />

dinâmica [13], que se baseia no princípio de que uma instância de um problema é resolvida<br />

aproveitando as soluções já computadas para instâncias menores deste problema.<br />

Programação dinâmica é aplicada tipicamente em problemas de otimização, para os<br />

quais deve-se construir um conjunto de escolhas visando obter uma solução ótima. À<br />

medida que estas escolhas são feitas, formam-se sub-problemas similares ao problema original.<br />

A idéia básica desta técnica é calcular o valor de cada sub-problema uma única vez,<br />

armazenando-o em uma tabela, e usar este valor sempre que o sub-problema correspondente<br />

reaparecer durante a execução do algoritmo que soluciona o problema.<br />

Existem duas características básicas que um problema de otimização deve ter para<br />

que a programação dinâmica possa ser aplicada: sub-estrutura ótima e sub-problemas<br />

que se sobrepõem. Dizemos que um problema exibe sub-estrutura ótima quando uma<br />

solução ótima para o problema é calculada a partir de soluções ótimas para sub-problemas<br />

similares, mas menores que o problema original. Em relação à segunda característica,<br />

para que um problema possua sub-problemas que se sobrepõem, o espaço de subproblemas<br />

deve ser pequeno, no sentido de que um algoritmo recursivo para o problema<br />

resolve os mesmos sub-problemas várias vezes, em vez de gerar diferentes sub-problemas.<br />

Tipicamente, o número total de sub-problemas distintos deve ser polinomial em relação<br />

ao tamanho da entrada.<br />

Dadas duas seqüências x e y, em vez de determinar a similaridade entre x e y tomando<br />

as duas seqüências inteiras, a solução pode ser obtida determinando todas as similaridades<br />

entre prefixos arbitrários das duas seqüências, iniciando pelos prefixos menores e utilizando<br />

os resultados já processados para resolver o problema para prefixos maiores.<br />

24


Este algoritmo reduziu a complexidade de tempo do problema de exponencial para<br />

quadrática, implementando um método de alinhamento global, que busca a similaridade<br />

máxima, pois prioriza os pareamentos (coincidências e divergências) e penaliza<br />

inserções e remoções (espaços) de bases, considerando o tamanho total das seqüências<br />

sendo comparadas. Este tipo de alinhamento é apropriado quando se espera encontrar<br />

similaridades ao longo de toda ou na maior parte das seqüências.<br />

Seguindo a técnica de programação dinâmica, a idéia básica do algoritmo consiste em<br />

dividir o problema de encontrar o melhor alinhamento entre duas seqüências em subproblemas<br />

de alinhar pares de bases, uma de cada seqüência, para encontrar subalinhamentos<br />

ótimos.<br />

alinhamentos possíveis:<br />

A solução de cada subproblema é dada pela escolha de um dos três<br />

• Alinhar as bases das duas seqüências;<br />

• Alinhar um espaço na primeira seqüência com a base da segunda seqüência;<br />

• Alinhar a base da primeira seqüência com um espaço na segunda seqüência.<br />

Para comparar duas seqüências x = x 1 x 2 . . . x |x| e y = y 1 y 2 . . . y |x| , onde |x| representa<br />

o comprimento da seqüência x e |y| o comprimento da seqüência y, o algoritmo gera uma<br />

matriz S |x|+1,|y|+1 , chamada de matriz de similaridade. Para cada célula s i,j da matriz,<br />

o algoritmo calcula a pontuação resultante de cada um dos três alinhamentos possíveis,<br />

selecionando o de maior valor, conforme a equação de recorrência do algoritmo de<br />

comparação global (equação 2.2).<br />

⎧<br />

⎪⎨ s i−1,j + ins<br />

s i,j = max s i−1,j−1 + sub<br />

⎪⎩<br />

s i,j−1 + del<br />

s i,0 = i × ins,<br />

s 0,j = j × del,<br />

i = 0, 1, . . . , |x|<br />

j = 1, 2, . . . , |y|<br />

(2.2)<br />

Os valores ins, sub e del são pontuações referentes a inserções, substituições e remoções,<br />

respectivamente. Conforme já citado, um esquema de pontuação muito utilizado [64]<br />

sugere ins = del = −2 que é a penalidade para inserir um espaço em uma das duas<br />

seqüências (alinhamento de uma base com um espaço). Para a substituição, temos sub =<br />

+1 se as duas bases x i e y j comparadas forem iguais ou sub = −1, caso contrário.<br />

A figura 2.14 mostra a matriz de similaridade obtida com a aplicação da equação de<br />

recorrência (equação 2.2) nas seqüências x = AACGT e y = AGT .<br />

A seqüência x é<br />

posicionada ao longo das colunas e y ao longo das linhas da matriz. A primeira linha e a<br />

primeira coluna, conforme a equação 2.2, são inicializadas com múltiplos da penalidade do<br />

espaço (−2 com o esquema de pontuação utilizado). Isto se deve à existência de apenas um<br />

alinhamento possível se uma das seqüências está vazia: apenas adicionar tantos espaços<br />

quanto forem os caracteres da outra seqüência. O escore deste alinhamento é −2k, onde k<br />

é o tamanho da seqüência não vazia. Para calcular as demais entradas (i, j) da matriz, só é<br />

preciso obter os valores computados para as três entradas anteriores: (i−1, j), (i−1, j −1)<br />

25


e (i, j−1), em função de haverem apenas três formas de obter um alinhamento entre x [1..i]<br />

e y [1..j]. De fato, para obter um alinhamento entre x [1..i] e y [1..j], temos as seguintes<br />

escolhas:<br />

• Alinhar x [1..i] com y [1..j − 1] e combinar um espaço com y [j], ou<br />

• Alinhar x [1..i − 1] com y [1..j − 1] e combinar x [i] com y [j], ou<br />

• Alinhar x [1..i − 1] com y [1..j] e combinar x [i] com um espaço.<br />

Figura 2.14: Matriz de similaridades das seqüências x = AACGT e y = AGC.<br />

Os ponteiros nessa matriz indicam qual dos três valores da equação de recorrência foi<br />

a origem da maior pontuação para a célula em questão. O preenchimento da matriz de<br />

similaridade pode ser feito tanto linha a linha, da esquerda para a direita em cada linha,<br />

ou coluna a coluna, de cima para baixo, em cada coluna. Qualquer outra ordem que torne<br />

disponível s [i, j − 1], s [i − 1, j − 1], s [i − 1, j] quando o valor de s [i, j] for computado,<br />

também pode ser utilizada.<br />

Com a matriz preenchida, o segundo passo é identificar o melhor alinhamento global.<br />

Para isso, é utilizado um procedimento de rastreamento no sentido inverso pela<br />

matriz, chamado backtracking, iniciando pelo elemento s [|x| + 1, |y| + 1], seguindo o direcionamento<br />

indicado pelos ponteiros de cada célula visitada até chegar na entrada s [0, 0]<br />

(figura 2.15). Cada ponteiro usado fornecerá uma coluna do alinhamento. Para uma dada<br />

célula (i, j) da matriz, se o ponteiro for uma seta horizontal, ela corresponde a um espaço<br />

inserido em x combinando com y [j]; se for uma seta vertical, então corresponde a x [i]<br />

combinado com um espaço inserido em y; finalmente, se for uma seta diagonal corresponde<br />

a x [i] combinando com y [j]. Como a primeira seqüência, x, é sempre colocada ao<br />

longo das colunas, um alinhamento ótimo pode ser facilmente construído da direita para<br />

a esquerda se tivermos a matriz S já calculada.<br />

Note que existem valores que são origem de mais de um vetor. Se um desses valores<br />

fizer parte do percorrimento reverso, todas as possibilidades deverão ser exploradas, pois<br />

cada uma delas representa um alinhamento ótimo.<br />

26


Figura 2.15: Obtenção do melhor alinhamento global.<br />

Para o exemplo anterior, o seguintes alinhamento ótimos são obtidos pelo percorrimento<br />

reverso, com x sendo a linha superior e y a inferior:<br />

A A C G T<br />

A − − G T<br />

e<br />

A A C G T<br />

− A − G T<br />

Para determinar a complexidade do algoritmo descrito, notamos que o número de<br />

operações executadas depende, essencialmente, do número de células da matriz que devem<br />

ser computados, isto é, do seu tamanho. Assim, supondo duas seqüências com comprimentos<br />

m e n, será gasto um tempo O(mn) nesses cálculos e este é o termo dominante<br />

da complexidade de tempo. O espaço utilizado também é proporcional ao tamanho da<br />

matriz. Se as seqüências tiverem o mesmo ou aproximadamente o mesmo tamanho, n,<br />

teremos complexidade de espaço e tempo de O(n 2 ), ou seja, uma complexidade quadrática.<br />

2.2.2.2 Comparação local<br />

O algoritmo de Needleman-Wunsch atribui uma penalidade constante, w k = kw 1 ,<br />

onde w 1 é a penalidade de inserção de um espaço, para seqüências de espaços, em uma<br />

das seqüências alinhadas. No entanto, sob o ponto de vista biológico, quando ocorrem<br />

eventos mutacionais em uma seqüência, a ocorrência de k espaços juntos é mais provável<br />

do que a ocorrência de k espaços isolados. Em 1981, Smith e Waterman generalizaram<br />

o algoritmo proposto por Needleman e Wunsch incorporando este critério, que atribui<br />

penalidades para espaços juntos considerando os seus tamanhos (w k ≤ kw 1 ), e propuseram<br />

um método de alinhamento local que, diferentemente do método de alinhamento global,<br />

identifica sub-regiões de maior similaridade entre as seqüências comparadas [66].<br />

Um alinhamento local de duas seqüências é definido como um alinhamento entre uma<br />

subseqüência da primeira seqüência com uma subseqüência da segunda. A similaridade<br />

das duas seqüências é definida como o escore máximo sobre todos os possíveis alinhamentos<br />

locais.<br />

Em várias aplicações biológicas, a identificação de regiões locais de similaridade em<br />

27


seqüências longas é mais significativa do que a similaridade entre as seqüências inteiras,<br />

pois o baixo valor desta pode esconder importantes fatos biológicos, só observáveis quando<br />

se consideram as sub-regiões.<br />

O algoritmo de Smith-Waterman é baseado em duas modificações no algoritmo de<br />

Needleman e Wunsch:<br />

• Quando o escore de um subalinhamento entre duas subsequências resulta em um<br />

valor negativo, é atribuído escore zero, que indica que o subalinhamento não deve<br />

ser prolongado;<br />

• Não basta considerar três células da matriz, pois em função da penalidade não constante<br />

para espaços juntos, é preciso verificar todas as células na mesma linha e todas<br />

as células na mesma coluna. Conseqüentemente, a interpretação dos valores da matriz<br />

é diferente. Cada entrada (i, j) irá armazenar o maior valor de um alinhamento<br />

entre um sufixo de x [1..i] e um sufixo de x [1..j].<br />

Neste caso, para encontrar o melhor alinhamento local, basta localizar a entrada da<br />

matriz que possui o maior valor de escore e aplicar o procedimento de rastreamento no<br />

sentido inverso até encontrar uma entrada com escore zero.<br />

No entanto, em função do tratamento diferenciado para a atribuição de penalidades<br />

para espaços juntos, o algoritmo de Smith-Waterman apresenta uma complexidade de<br />

tempo de O(n 3 ).<br />

Gotoh [23], em 1982, propôs uma forma de reduzir essa complexidade de tempo, modificando<br />

o algoritmo de Smith-Waterman por meio de uma limitação na métrica utilizada<br />

para espaços juntos. Sem afetar o critério de computar espaços juntos de tamanhos variados,<br />

ele conseguiu reduzir a complexidade de tempo para O(n 2 ), utilizando uma forma<br />

especial de penalidade para estes espaços juntos, chamada função de espaços juntos<br />

afim, expressa pela fórmula w k = u +vk (u, v ≤ 0), onde u expressa a penalidade para inserir<br />

o primeiro espaço, v indica o custo para estendê-lo e k indica o tamanho do conjunto<br />

de espaços juntos. A equação 2.3 representa a proposta de Gotoh.<br />

⎧<br />

⎪⎨ p i,j<br />

s i,j = max s i−1,j−1 + sub<br />

⎪⎩<br />

q i,j<br />

{<br />

si−1,j + w<br />

p i,j = max<br />

1<br />

p i−1,j + v<br />

{<br />

si,j−1 + w<br />

q i,j = max<br />

1<br />

q i,j−1 + v<br />

s i,0 = p i,0 = q i,0 = 0,<br />

s 0,j = p 0,j = q 0,j = 0,<br />

i = 0, 1, . . . , |x|<br />

j = 1, 2, . . . , |y|<br />

(2.3)<br />

Se a penalidade do espaço for constante como no algoritmo de Needleman-Wunsch,<br />

a equação de recorrência do algoritmo de comparação local pode ser reduzida para a<br />

equação 2.4.<br />

28


⎧<br />

⎪⎨<br />

s i,j = max<br />

⎪⎩<br />

s i−1,j + w 1<br />

s i−1,j−1 + sub<br />

s i,j−1 + w 1<br />

0<br />

s i,0 = 0,<br />

s 0,j = 0,<br />

i = 0, 1, . . . , |x|<br />

j = 1, 2, . . . , |y|<br />

(2.4)<br />

Embora não seja a equação mais correta do ponto de vista biológico, essa equação foi<br />

a escolhida para a implementação feita nessa dissertação. A idéia é atacar o problema<br />

com uma abordagem mais simples, e uma vez conhecidas suas peculiaridades, estender a<br />

solução obtida para situações mais complexas.<br />

Espaço Linear<br />

A complexidade quadrática em espaço do algoritmo de Smith-Waterman, que reflete<br />

a quantidade de memória necessária, pode torná-lo inviável quando seqüências muito<br />

longas forem comparadas, já que manter a matriz de similaridades totalmente carregada<br />

em memória possui um custo muito alto. No entanto, para o cálculo da posição s i,j , são<br />

necessários apenas os valores s i−1,j , s i−1,j−1 e s i,j−1 . Logo, é preciso manter em memória<br />

apenas a linha atual que está sendo calculada e a linha anterior, para consulta. Com isto,<br />

a complexidade de espaço que era O(n 2 ) passa a ser O(2n). A complexidade de tempo<br />

permanece O(n 2 ).<br />

29


Capítulo 3<br />

<strong>HARDWARE</strong><br />

3.1 Sistemas Dedicados<br />

Arquiteturas tradicionais de computadores podem resolver uma diversidade muito<br />

grande de problemas de computação, desde que lhes sejam submetidos diferentes programas,<br />

cada qual com um propósito específico. Para a maioria das tarefas de computação,<br />

esta abordagem, centrada na utilização de processadores de propósito geral (GPP), é mais<br />

barata e rápida.<br />

O principal foco do projeto de GPPs reside, pois, no desempenho e na funcionalidade<br />

geral a ser proporcionada. Contudo, os custos de fabricação e projeto de arquiteturas<br />

baseadas em processadores de propósito geral estão aumentando com rapidez [5]. Tais<br />

custos compreendem três perceptíveis aspectos:<br />

• Custos de hardware: os processadores de propósito geral são maiores e mais complexos<br />

do que o necessário para resolver uma tarefa específica;<br />

• Custos de projeto: unidades funcionais, raramente usadas em determinadas aplicações,<br />

podem estar presentes em GPPs, tendendo a consumir uma parte considerável do<br />

esforço de projeto;<br />

• Custos de energia: muita energia é desperdiçada por unidades funcionais ou blocos<br />

que não são usados durante grande porção do tempo de processamento.<br />

Considerando-se aplicações específicas ou a exigência de requisitos em termos de consumo,<br />

velocidade, tamanho e custos, podem ser adotados tipos especiais de processadores,<br />

voltados para a aplicação em questão ou otimizados com vistas ao conjunto de requisitos<br />

especificados. Sob esta ótica, somente as unidades funcionais necessárias, altamente otimizadas<br />

para um conjunto de problemas do mesmo tipo, estão presentes, o que redunda<br />

em economia de área e energia para o algoritmo específico às aplicações.<br />

Dessa forma, sistemas computacionais dedicados são usados tipicamente em aplicações<br />

específicas onde os sistemas de propósito geral não conseguem obter o desempenho esperado.<br />

30


No desenvolvimento desses circuitos dedicados, o desempenho depende, na maioria das<br />

vezes, mais da arquitetura do circuito do que da tecnologia de fabricação [12]. Este conceito<br />

é largamente utilizado no projeto de sistemas de tratamento de sinais, por exemplo,<br />

onde um processador com baixo custo executa uma filtragem mais rapidamente que um<br />

poderoso Pentium®.<br />

Para decidir sobre a utilização de um sistema dedicado e a arquitetura mais adequada,<br />

diversos aspectos devem ser levados em conta.<br />

Unidades simples e regulares<br />

Como os sistemas dedicados possuem aplicação limitada, seu custo deve ser menor<br />

que o benefício da utilização de uma arquitetura de propósito específico. Além do mais,<br />

como os sistemas dedicados não são produzidos em larga escala, os custos de projeto<br />

são mais importantes que os custos da fabricação das peças. Dessa forma, os custos de<br />

projeto devem ser baixos de modo a tornar esses sistemas mais atrativos que os sistemas<br />

de propósito geral.<br />

Felizmente, a utilização de arquiteturas apropriadas pode reduzir significativamente<br />

os custos de sistemas de propósito específico. Se uma determinada estrutura puder ser<br />

decomposta em poucas unidades menores e mais simples, e essas serem utilizadas repetidamente,<br />

uma grande economia pode ser obtida. Isto é especialmente verdade em projetos<br />

de circuito integrados VLSI, onde um simples chip contém milhares de componentes. Em<br />

adição, sistemas baseados em unidades simples e regulares são modulares e podem se<br />

ajustar a diversos critérios de performance.<br />

Operações de entrada e saída<br />

Tipicamente, um sistema dedicado deve se comunicar com o mundo externo, recebendo<br />

dados e entregando resultados. Não adianta o sistema fornecer resultados em uma velocidade<br />

maior que o mundo externo é capaz de recebê-los. Assim, as operações de entrada e<br />

saída (E/S) afetam bastante o desempenho geral de sistemas com arquiteturas específicas.<br />

Outra dificuldade é quando cálculos extensos devem se feitos em sistemas de pequeno<br />

porte. Neste caso, a computação deve ser decomposta em partes menores e os dados temporários<br />

gerados armazenados para futuras referências. Isso aumenta muito a comunicação<br />

com o ambiente externo.<br />

Assim, várias considerações devem ser feitas sobre como minimizar o acesso externo,<br />

como os requisitos de E/S afetam o sistema e sua memória interna e como a largura de<br />

banda das operações de entrada e saída pode limitar o ganho de velocidade (speed-up).<br />

31


Concorrência<br />

O hardware é inerentemente paralelo. Ao se ligar um circuito eletrônico, todos os seus<br />

transistores estão aptos a realizar alguma função. A utilização conveniente do paralelismo<br />

encontra, basicamente, duas dificuldades: raciocínio serial e dependência de dados. O<br />

primeiro problema é inerente à nossa forma de raciocinar, o segundo, advém das aplicações,<br />

pois alguns resultados só podem ser processados após o término de outros.<br />

Em termos de paralelismo, deve-se distinguir o modelo de hardware que se está tratando,<br />

ou pelo menos, seu nível de abstração. Existe o paralelismo explícito de processos,<br />

formado por um conjunto de máquinas, como em uma rede de computadores, ou por um<br />

conjunto de processadores atuando em conjunto.<br />

Um outro nível de paralelismo é aquele de processos de hardware completamente distintos,<br />

executando funções complementares. Como exemplo, podemos ter um microprocessador<br />

operando em paralelo com um temporizador e uma interface serial.<br />

Finalmente, tem-se o paralelismo em nível de operações de hardware. Por exemplo,<br />

no cálculo da equação y = x 2 + 3x + 1, a exponenciação pode ser feita em paralelo com a<br />

multiplicação, pois não há dependência de dados para essas operações. Em geral, quanto<br />

mais paralelismo estiver presente, mais rapidamente um algoritmo pode ser computado.<br />

Contudo, maior será o preço do hardware final, seja na utilização de uma maior área de<br />

silício em um CI, seja na quantidade de células lógicas necessárias em um FPGA.<br />

Para limitar esse problema no paralelismo de operações, a questão a ser respondida é<br />

qual o número mínimo de passos de relógio e qual o mínimo de componentes necessários<br />

para executar o algoritmo na maior velocidade possível. As duas características combinadas<br />

tendem a ser conflitantes. Para maior velocidade, precisa-se de um mínimo de passos,<br />

mas para executar o algoritmo em um mínimo de passos, maior quantidade de hardware<br />

deve estar disponível.<br />

Existem algoritmos que permitem descobrir o menor número de passos necessários,<br />

dada uma restrição de recursos. Entre esses, podemos citar o ASAP (as soon as possible),<br />

ALAP (as late as possible) e ordenação de lista (list scheduling) [20][48][49]. Nesses<br />

algoritmos, as operações são distribuídas em diversos passos de relógio, com o ASAP priorizando<br />

as operações para o primeiro ciclo possível, o ALAP colocando as operações o<br />

mais próximo do último ciclo de controle possível e a ordenação por listas utilizando as<br />

tabelas do ASAP e ALAP para efetuar suas decisões.<br />

Controle e comunicação<br />

Quando um elevado número de processadores opera em paralelo, os custos de controle<br />

(sincronização) e comunicação começam a ser tornar significativos. Se a granularidade for<br />

fina, para facilitar o balanceamento de carga, podem ocorrer sobrecargas de comunicação<br />

32


e sincronização.<br />

Na análise do sistema, devemos verificar se o algoritmo a ser abordado com a arquitetura<br />

dedicada suporta um alto grau de paralelismo e ao mesmo tempo pode ser<br />

implementado com um controle e comunicação simples e regular.<br />

No paralelismo de operações, também pode-se ter um alto custo de comunicação e<br />

controle. Imagine que uma constante deva ser somada a 100 números, disponíveis em 100<br />

registradores diferentes. Um conjunto de 100 somadores permitiria a soma em apenas<br />

um ciclo de relógio. Se cada registrador pudesse ser carregado no mesmo ciclo, a cada<br />

ciclo ter-se-iam 100 somas. Contudo, o custo de tal arquitetura é muito alto, pois além<br />

dos 100 somadores e registradores, seriam necessários 100*n bits de entrada, onde n é<br />

o número de bits de cada registrador, e, provavelmente, muito mais bits de saída pois<br />

o resultado de cada soma será maior que os valores somados. Para piorar, se os dados<br />

para os registradores vierem de uma memória externa e também devam ser armazenados<br />

externamente, o problema adquire novas dimensões.<br />

A conclusão é que, embora o paralelismo efetivamente acelere computações, seu custo<br />

deve ser medido não somente em termos de operadores a mais, mas também no custo do<br />

controle e comunicação para manterem o circuito paralelo ativo e funcional.<br />

3.2 Arquiteturas Sistólicas<br />

Uma possível solução para o projeto de sistemas dedicados são as arquiteturas sistólicas.<br />

Esse conceito foi desenvolvido na universidade Carnegie-Mellon e originalmente proposto<br />

para a implementação em VLSI de algumas operações sobre matrizes.<br />

A origem desse nome vem da sístole, movimento de contração no qual o coração bombeia<br />

o sangue para as artérias, da mesma forma que a memória “bombeia” dados para<br />

dentro da estrutura sistólica e que depois retornam processados para essa memória (figura<br />

3.1).<br />

Figura 3.1: Aspecto geral de uma arquitetura sistólica.<br />

Um sistema sistólico consiste em um conjunto de células (chamadas de elementos<br />

de processamento) interconectadas, cada uma capaz de realizar alguma operação simples<br />

[37]. Além disso, o controle e a comunicação entre as células é simples e regular.<br />

Tipicamente, as células de uma estrutura sistólica estão organizadas na forma de matrizes<br />

33


(unidimensionais ou bidimensionais) ou em árvores (figura 3.2). A comunicação com o<br />

mundo externo ocorre apenas nas células das “bordas” do sistema.<br />

Figura 3.2: Alguns tipos de estruturas sistólicas.<br />

O princípio básico de um sistema sistólico é substituir um elemento de processamento<br />

complexo por uma matriz de elementos de processamento simples e, conseqüentemente,<br />

rápidos, todos capazes de manipular eficientemente um particular dado de entrada (que<br />

percorre a estrutura), atingindo altas taxas de processamento com modesta utilização de<br />

memória.<br />

Para se avaliar a possibilidade de utilização dessa arquitetura em um particular problema,<br />

as seguintes características do algoritmo ou sistema devem ser analisadas:<br />

1. múltiplos usos de um único dado de entrada: devido a essa propriedade, pode-se<br />

obter alta performance com poucas operações de entrada e saída;<br />

2. uso intensivo de concorrência: o poder elevado de processamento de uma arquitetura<br />

sistólica vem do uso de muitas células simples e rápidas atuando em paralelo no lugar<br />

de um poderoso e único processador (ou poucos processadores);<br />

3. pode-se decompor a solução em poucas estruturas simples: como uma grande quantidade<br />

de elementos de processamento é utilizada, não deve haver muita variedade<br />

desses elementos e eles devem ser o mais simples possível;<br />

4. controle do fluxo de dados simples e regular: em um sistema sistólico, o único sinal<br />

global deve ser o relógio do sistema. Os outros sinais de controle e comunicação<br />

devem ficar restritos às células adjacentes da estrutura.<br />

Resumindo, um sistema sistólico baseado nesses critérios será simples, modular e expansível,<br />

com alta performance e possuindo poucos acessos à memória externa.<br />

Devido a essas propriedades, as arquiteturas sitólicas são adequadas para tarefas computacionalmente<br />

intensas, mas com poucas operações de entrada e saída.<br />

34


Dentre as possíveis aplicações para esse tipo de arquitetura, destacam-se: DFT (Discrete<br />

Fourier Transform) e FFT (Fast Fourier Transform), convolução, interpolação, multiplicação<br />

de matrizes, triangularização de matrizes (solução de sistemas lineares), ordenamentos,<br />

reconhecimento de voz, programação dinâmica, etc.<br />

3.3 Sistemas Reconfiguráveis<br />

A evolução contínua dos algoritmos e a diversidade das aplicações têm levado à concepção<br />

de ambientes de hardware baseados em arquiteturas reconfiguráveis que possibilitem<br />

a implementação de diferentes algoritmos em um mesmo suporte físico.<br />

Muitas aplicações emergentes em telecomunicações e multimídia necessitam que suas<br />

funcionalidades permaneçam flexíveis mesmo depois do sistema ter sido manufaturado [26].<br />

Tal flexibilidade é fundamental, uma vez que requisitos dos usuários, características dos<br />

sistemas, padrões e protocolos podem mudar durante a vida do produto. Essa maleabilidade<br />

também pode prover novas abordagens de implementação voltadas para ganhos de<br />

desempenho, redução dos custos do sistema ou redução do consumo geral de energia.<br />

A flexibilidade funcional é comumente obtida através de atualizações de software, mas<br />

desta forma a mudança é limitada somente à parte programável dos sistemas. Desenvolvimentos<br />

recentes na tecnologia de matrizes de elementos lógicos programáveis no campo<br />

(Field-Programmable Gate Arrays, ou FPGAs) têm introduzido suporte para modificações<br />

rápidas e em tempo de execução do hardware do sistema.<br />

Essas modificações referem-se a mudanças em circuitos digitais via reconfiguração.<br />

A implementação de sistemas que exigem flexibilidade, alto desempenho, alta taxa de<br />

transferência de dados e eficiência no consumo de energia são possibilitadas por essas<br />

tecnologias. Isto inclui aplicações de televisão digital, sistemas de computação de alto desempenho,<br />

processamento de imagens em tempo real, produtos para consumo atualizáveis<br />

remotamente, entre outros.<br />

Além das características citadas acima, a reconfigurabilidade também contribui para<br />

a economia de recursos: quando uma dada tarefa pode ser realizada em várias fases, uma<br />

diferente configuração pode ser carregada para cada fase seqüencialmente [70]. Desta<br />

forma o tamanho do sistema pode ser menor, o que implica na redução de preço.<br />

Para finalizar, a reconfigurabilidade também faz do desenvolvimento e teste de hardware<br />

tarefas mais rápidas e mais baratas. Com o advento das FPGAs, a engenharia de<br />

hardware foi capacitada a implementar projetos em nível de chip sem ter que fabricá-lo.<br />

Segundo Page [54], há cinco estratégias de projeto pelas quais programas podem ser<br />

embutidos em arquiteturas reconfiguráveis, sendo cada modelo mais apropriado a um<br />

específico escopo de aplicações, apresentando diferentes compromissos entre custo e desempenho<br />

(figura 3.3):<br />

• Modelo de hardware puro: um dado algoritmo é convertido em uma única descri-<br />

35


ção de hardware a qual é carregada em um FPGA. A configuração dá-se em tempo<br />

de projeto e este modelo pode ser implementado a partir de linguagens de descrição<br />

de hardware convencionais e das ferramentas de síntese atualmente disponíveis. É<br />

interessante para o projeto e rápida prototipação de circuitos dedicados;<br />

• Modelo de processadores voltados para uma aplicação: neste caso, um algoritmo<br />

é compilado e obtêm-se dois resultados: um código de máquina abstrata e um<br />

processador abstrato. A seguir, as partes são otimizadas para produzir a descrição<br />

de um processador de aplicação específica e o código de máquina para ele;<br />

• Modelo de reutilização seqüencial: a principal utilidade desta estratégia é notada<br />

em situações nas quais determinado algoritmo é por demais extenso para ser<br />

implementado nos dispositivos disponíveis, ou ainda, quando o projeto apresenta<br />

restrições de área por razões econômicas ou de engenharia. Deste modo, o projeto<br />

é subdividido em várias partes, as quais são submetidas a diferentes dispositivos,<br />

redundando em um conjunto de passos de reconfiguração. Os ganhos relacionados<br />

com a reutilização do hardware devem ser balanceados com o tempo que é gasto<br />

com a reconfiguração;<br />

• Modelo de múltiplo uso simultâneo: se porventura houver uma ampla disponibilidade<br />

de dispositivos programáveis, vários algoritmos podem estar residentes e<br />

serem executados simultaneamente, interagindo em diferentes graus de acoplamento<br />

com o processador hospedeiro. É um modelo menos comum, requerendo mais área<br />

do que a estratégia de reutilização seqüencial, mas é um método interessante para<br />

a exploração da computação reconfigurável.<br />

• Modelo de uso sob demanda: é muito interessante para a computação reconfigurável.<br />

Pode ser adotado em uma ampla variedade de aplicações quando existe a<br />

possibilidade de sistemas computacionais serem construídos onde o hardware não<br />

existe todo ao mesmo tempo, mas cuja demanda de tempo-real do sistema dita qual<br />

parte do hardware deve ser construída e qual parte deve ser destruída. Há uma<br />

analogia razoável com sistemas de memória virtual, e por isto esse esquema pode<br />

ser chamado de “hardware virtual”. Sua utilização cabe perfeitamente em sistemas<br />

de tempo real e em sistemas que apresentam uma grande quantidade de funções e<br />

operações não-concorrentes.<br />

Sob a ótica da capacidade de reconfiguração proporcionada pelo projeto da arquitetura<br />

reconfigurável, Adário [5] apresenta uma generalização dos modelos de execução definidos<br />

por Page. Esta abordagem divide os modelos de projeto em três classes de capacidade<br />

de programação, considerando o número de configurações e o instante em que ocorre<br />

cada reconfiguração:<br />

36


Figura 3.3: Modelos segundo a classificação de Page.<br />

• Projeto Estático: o circuito possui uma única configuração que nunca é modificada.<br />

O dispositivo programável é totalmente programado para executar uma única<br />

função que permanece inalterada durante toda vida útil do sistema. Esta classe não<br />

explora a flexibilidade provida pela reconfiguração; a única vantagem aproveitada<br />

diz respeito às facilidades de projeto e prototipação conferidas pela reconfiguração;<br />

• Projeto Estaticamente Reconfigurável: o circuito apresenta várias configurações,<br />

e as reconfigurações acontecem apenas ao final de cada tarefa de processamento. Dependendo<br />

da granularidade das tarefas executadas entre sucessivas reconfigurações,<br />

pode-se dizer que este modelo efetua reconfiguração em tempo de execução. Neste<br />

modelo, os dispositivos programáveis são usados de forma mais proveitosa. Arquiteturas<br />

desta classe são chamadas de SRA – Statically Reconfigurable Architecture;<br />

• Projeto Dinamicamente Reconfigurável: o circuito também apresenta várias<br />

configurações e as reconfigurações acontecem, de fato, em tempo de execução. Este<br />

tipo de projeto utiliza eficientemente as arquiteturas reconfiguráveis. O overhead<br />

acarretado pela reconfiguração em tempo de execução precisa ser bem caracterizado<br />

no domínio do conjunto das possíveis configurações. As arquiteturas resultantes<br />

desta classe são denominadas DRA – Dynamically Reconfigurable Architecture.<br />

As vantagens que podem ser auferidas da reconfiguração em tempo de execução dependem<br />

muito do algoritmo em questão e da granularidade das tarefas que o compõem.<br />

Por sua vez, o overhead de reconfiguração está fortemente vinculado à microarquitetura<br />

das FPGAs utilizadas.<br />

37


Geralmente, as aplicações, cuja implementação em arquiteturas reconfiguráveis é desejável,<br />

apresentam três características básicas, a saber[4]:<br />

• Regularidade: implica na execução das mesmas operações básicas repetidamente;<br />

• Alta concorrência: refere-se à existência de um grande número de operações que<br />

são efetuadas concomitantemente;<br />

• Dados com granularidade fina: diz respeito ao pequeno tamanho dos operandos.<br />

Dadas tais características, podem ser arroladas aplicações passíveis de implementação<br />

profícua em arquiteturas reconfiguráveis. Segundo Adário[4], merecem especial atenção<br />

aplicações voltadas para: criptografia e compressão, casamento de padrões, ordenação,<br />

simulação de sistemas físicos, processamento de vídeo e de imagens, aritmética especializada.<br />

Para que se possa tirar proveito de uma implementação em arquitetura reconfigurável,<br />

dois passos devem ser seguidos:<br />

• Identificar, em um aplicação, a porção regular e a seção crítica ao desempenho;<br />

• Avaliar as opções para o mapeamento da aplicação em dispositivos programáveis.<br />

Esta consideração é deveras importante, pois a melhor implementação em uma arquitetura<br />

reconfigurável pode ser muito diferente, no que tange ao estilo de programação,<br />

de uma implementação baseada em GPP.<br />

3.3.1 FPGA<br />

Os FPGAs (Field-Programmable Gate Arrays) foram introduzidos no mercado em 1985<br />

pela Xilinx e foram responsáveis pela grande expansão dos sistemas reconfiguráveis. Esses<br />

dispositivos permitem a integração de lógica e memória em um único circuito, além de<br />

serem programáveis, permitindo a reconfiguração do hardware e rápida prototipação de<br />

sistemas digitais.<br />

A estrutura básica do FPGA (figura 3.4) pode variar segundo o fabricante do mesmo,<br />

mas são compostos, basicamente, dos seguintes recursos:<br />

1. Funções lógicas programáveis de n entradas (blocos lógicos), onde n varia com a<br />

família e fabricante do FPGA;<br />

2. Rede de conexão para interligar entre os diversos blocos lógicos existentes;<br />

3. Flip-flops ou registradores (blocos lógicos) para o armazenamento de informações;<br />

4. Amplificadores de corrente de entrada e saída;<br />

38


Figura 3.4: Estrutura interna de um FPGA.<br />

5. Memória RAM interna nos dispositivos mais modernos.<br />

FPGAs que possuem um pequeno número de poderosos blocos lógicos reconfiguráveis<br />

são classificados como FPGAs com granulações grandes, enquanto que os que possuem<br />

grande número de blocos lógicos simples, são classificados como FPGAs com granulações<br />

pequenas [70]. Um único bloco lógico em um FPGA com grande granulação é capaz de<br />

adicionar ou comparar dois números, enquanto que em um FPGA com granularidade fina<br />

são necessários mais de um bloco lógico para efetuar as mesmas operações.<br />

3.3.2 Síntese de sistemas reconfiguráveis<br />

Os FPGAs são componentes bastante versáteis, capazes de implementar uma infinidade<br />

de circuitos lógicos combinacionais e seqüenciais. Entretanto, a tarefa de transformar o<br />

projeto de um circuito digital em um circuito mapeado na tecnologia de FPGA é bastante<br />

complexa.<br />

Além disso, os FPGAs possuem uma arquitetura interna que, embora possua um núcleo<br />

comum, varia dentro de famílias de um mesmo fabricante e também entre fabricantes<br />

diferentes. Devido a essa diversidade, uma outra tarefa difícil para o projetista é conhecer<br />

todas essas arquiteturas internas e manipular seus elementos programáveis (EABs, CLBs<br />

e interconexões) da forma mais otimizada para a arquitetura em questão.<br />

Para automatizar os processos envolvidos nos projetos com esses dispositivos e abstrair<br />

as dependências tecnológicas, diversas ferramentas foram criadas, algumas de uso geral<br />

e outras dependentes da tecnologia de um particular fabricante. A grande utilização<br />

dos FPGAs é devida ao suporte dado por esses programas de automação de projetos<br />

eletrônicos.<br />

Fluxo de projeto<br />

O fluxo de projeto para FPGA pode ser dividido basicamente nas seguintes fases:<br />

especificação do circuito, síntese, simulação e configuração do FPGA, como pode ser visto<br />

39


na figura 3.5.<br />

O projeto começa com a descrição do circuito. Nesta etapa pode-se optar por duas<br />

metodologias de especificação, o desenho de um diagrama esquemático ou a utilização de<br />

uma linguagem de descrição de hardware. A primeira abordagem normalmente requer ferramentas<br />

proprietárias do fabricante do FPGA escolhida, prejudicando sua portabilidade.<br />

Além disso, as alterações no projeto são mais complexas que nas linguagens de descrição.<br />

Por esses motivos, deve ser evitada.<br />

Figura 3.5: Fluxo de projeto utilizando FPGAs.<br />

Para uma especificação baseada em linguagens de descrição de hardware, as linguagens<br />

Verilog [18] e VHDL [10] são as mais utilizadas. Verilog é utilizado basicamente no mercado<br />

americano, enquanto que a linguagem VHDL é um padrão mundial.<br />

A etapa de síntese, em geral, é executada por uma ferramenta do fabricante do FPGA<br />

escolhida, pois está intimamente ligada com sua arquitetura interna. Ela pode ser dividida<br />

nas seguintes partes:<br />

• otimização lógica: manipula as equações lógicas geradas na etapa inicial, visando<br />

otimizar o circuito final;<br />

• mapeamento tecnológico: consiste na transformação das equações lógicas otimizadas<br />

em um circuito que utiliza os blocos lógicos presentes no FPGA alvo. Nesta fase<br />

também são realizadas minimizações nas quantidades de blocos lógicos e caminho<br />

crítico (caminho com maior atraso combinacional) do circuito;<br />

• posicionamento: é definida a distribuição os blocos lógicos na matriz do FPGA. Para<br />

isso, o arranjo dos blocos tenta minimizar o comprimento total das interconexões;<br />

• roteamento: é quando ocorre a interligação dos blocos lógicos dispostos na matriz<br />

do FPGA por intermédio da rede de interconexões programável.<br />

40


A síntese, embora totalmente automatizada, permite a intervenção de projetistas experientes,<br />

principalmente na fase de posicionamento, que é bastante crítica para a performance<br />

geral do sistema.<br />

Na fase de simulação é efetuado um teste da lógica do circuito descrito. Vários<br />

estímulos são aplicados em suas entradas e depois é verificado o comportamento ou as<br />

respostas obtidas para esses estímulos. Além disso, é possível verificar os atrasos internos,<br />

ou seja, tempo que um sinal de saída leva para ser alterado após a transição de um sinal<br />

de entrada, determinar caminhos críticos e a velocidade máxima de operação.<br />

Já no processo de síntese, é gerado um arquivo de configuração do FPGA. Não sendo<br />

descoberto nenhum problema durante a simulação, esse arquivo pode ser enviado para o<br />

FPGA, de maneira que ele passe a operar de acordo com o circuito projetado. Como o<br />

FPGA é volátil, o arquivo gerado pode ser armazenado em uma EEPROM (electrically<br />

erasable programable read-only memory) permitindo que o FPGA se auto configure toda<br />

vez que o circuito é ligado.<br />

3.3.3 Linguagens de descrição de hardware e VHDL<br />

No início dos anos 80, o departamento de defesa americano (DoD) estava preocupado<br />

com a manutenção de seus equipamentos eletrônicos e em aumentar a produtividade dos<br />

projetistas, devido aos constantes avanços tecnológicos que ocorrem na área. Além disso,<br />

várias empresas forneciam equipamentos e desenvolviam projetos para governo.<br />

No programa VHSIC (very high speed integrated circuits) foi feito um esforço de padronização<br />

por uma linguagem que pudesse descrever a estrutura e funcionalidade dos<br />

circuitos integrados, que fosse de fácil entendimento por qualquer projetista e possibilitasse<br />

simulações dos circuitos nela descritos. Desse modo, projetos que utilizassem essa<br />

linguagem poderiam ser facilmente migrados de uma tecnologia para outra, acompanhando<br />

as evoluções do setor, e os projetos desenvolvidos para o DoD pelos diversos fornecedores<br />

seriam padronizados e sua manutenção facilitada.<br />

Esse esforço resultou na linguagem VHDL (VHSIC hardware description language) [42],<br />

que passou a ser um padrão aceito pelo IEEE [1]. Como todos os padrões do IEEE, a<br />

VHDL é revista a cada cinco anos, e em 1992, foi proposta uma versão revisada, adotada<br />

em 1993 com o nome de IEEE-1164.<br />

No início da década de 90, a VHDL foi usada primeiramente para projetos em ASIC<br />

e foram desenvolvidas ferramentas para automatizar o processo de criação e otimização<br />

das implementações. Na segunda metade da década, o uso de VHDL em síntese moveu-se<br />

para a área de dispositivos lógicos programáveis (CPLDs e FPGAs).<br />

VHDL possibilita descrições tanto em baixo nível (conexões entre componentes como<br />

portas E, OU, etc.) quanto em nível mais abstrato de comportamento. Assim, as construções<br />

em VHDL são divididas em três categorias, cada uma significando um nível diferente<br />

de abstração:<br />

41


• Comportamental: o circuito é definido na forma de um algoritmo, utilizando construções<br />

similares àquelas de linguagens de programação;<br />

• Fluxo de dados: tem-se a visão dos dados como um fluxo através do circuito, da<br />

entrada até a saída. Uma operação é definida em termos de uma coleção de dados,<br />

expressados como comandos concorrentes;<br />

• Estrutural: a visão mais próxima do hardware. Um modelo onde os componentes<br />

do circuito são instanciados e as ligações entre eles descritas.<br />

Contudo, a maioria das ferramentas de síntese ainda não aceita descrições puramente<br />

comportamentais, onde não se tem um relógio explícito, não se consegue inferir os registradores<br />

e o conjunto de comandos é seqüencial, quase como um programa em linguagem<br />

C. Assim, as descrições comportamentais, embora mais abstratas, devem levar em conta<br />

diversos aspectos de um projeto de hardware para poderem ser sintetizadas corretamente.<br />

A estrutura de um programa escrito em VHDL baseia-se em níveis hierárquicos. Resumidamente,<br />

podemos definir 4 desses níveis:<br />

• Pacotes: permite agregar em um projeto de vários componentes ou entidades previamente<br />

definidos. Pode ser visto como uma “biblioteca” de componentes dentro de<br />

um projeto. Aceita também definições de tipos e funções;<br />

• Entidades: uma entidade é qualquer componente VHDL que tenha um conjunto de<br />

portas de comunicação, com entradas e saídas. Uma entidade descreve um componente<br />

como uma “caixa-preta”, ou seja, apenas suas portas de entrada e saída são<br />

visíveis;<br />

• Arquitetura: é um conjunto de primitivas em VHDL que farão a efetiva descrição do<br />

hardware. É aqui que as abordagens comportamental, fluxo de dados ou estrutural<br />

são definidas;<br />

• Processos: é uma abstração de hardware que está sempre atuando. Um processo é<br />

basicamente o modelo de um componente físico, que possui uma lista de sinais dos<br />

quais depende (chamada de lista de sensitividade). Os processos podem ser síncronos<br />

ou assíncronos e diversos deles podem ser definidos dentro de um arquitetura. Os<br />

processos descritos em uma arquitetura são sempre concorrentes, mas o fluxo dentro<br />

de um processo é seqüencial.<br />

Outra característica importante da VHDL é que ela é uma linguagem fortemente tipada,<br />

aceitando poucas conversões entre os tipos de dados aceitos.<br />

Um programa escrito em VHDL possui o seguinte aspecto:<br />

42


-- Uso de bibliotecas. A terceira cláusula use faz refer^encia a um pacote<br />

-- chamado componentes<br />

library IEEE;<br />

use ieee.std_logic_1164.all;<br />

use ieee.std_logic_unsigned.all;<br />

use work.componentes.all;<br />

-- Definiç~ao da entidade<br />

entity MULT is<br />

generic (size : integer := 16);<br />

port (NUM1, NUM2 : in std_logic_vector(size-1 downto 0);<br />

CLK, RST : in std_logic;<br />

RES: out std_logic_vector(size*2-1 downto 0));<br />

End MULT;<br />

-- Definiç~ao da arquitetura<br />

architecture CALC of MULT is<br />

-- Definiç~ao de sinais internos<br />

signal X,X1 : std_logic_vector(size downto 0);<br />

begin<br />

-- Definiç~ao de um processo síncrono<br />

REG: process (CLK, RST)<br />

Begin<br />

if RST = ’1’ then<br />

ESTADO


• a descrição da especificação do circuito serve como documentação e explicita os<br />

objetivos do projeto;<br />

• o uso da síntese melhora a produtividade;<br />

• a padronização dessas linguagens resulta em portabilidade, tornando o código reutilizável<br />

em diferentes ambientes de desenvolvimento.<br />

Evidentemente, esse estilo de projeto não possui apenas vantagens. Alguns problemas<br />

permanecem ou são criados pela utilização dessas linguagens:<br />

• investimento inicial em educação e treinamento dos projetistas;<br />

• a síntese é limitada e muitos problemas devem ser particionados à mão (mas, nesse<br />

caso, seriam mais dificilmente resolvidos pelo projetista humano);<br />

• não é solução para todo tipo de projeto;<br />

• não atende a algumas restrições sérias, por exemplo, circuitos voltados ao baixo<br />

consumo, uso de pipeline, etc;<br />

• não existe (ainda) a síntese de circuitos analógicos e mistos.<br />

3.4 Somadores<br />

3.4.1 Meio-somador (half adder)<br />

Executa a soma entre dois bits, gerando uma saída S dada pela soma desses dois bits<br />

e uma saída V A que representa o “vai-um” dessa soma, segundo a tabela a seguir.<br />

Tabela 3.1: Tabela-verdade do meio-somador (half adder).<br />

A 0 B 0 V A0 S 0<br />

0 + 0 = 0 0<br />

0 + 1 = 0 1<br />

1 + 0 = 0 1<br />

1 + 1 = 1 0<br />

Da tabela 3.1, obtêm-se as seguintes equações que descrevem a relação entre as entradas<br />

e as saídas de um meio-somador:<br />

S 0 = A 0 ⊕ B 0 e (3.1)<br />

o que leva à implementação esquematizada na figura 3.6.<br />

V A0 = A 0 · B 0 , (3.2)<br />

44


Figura 3.6: Diagrama esquemático do meio-somador.<br />

3.4.2 Somador completo (full adder)<br />

Executa a soma entre três bits sendo um deles o “vem-um” recebido de um bit menos<br />

significativo. Gera uma saída S dada pela soma desses bits e uma saída V que representa<br />

o “vai-um” dessa soma.<br />

A seguir, é apresentada a tabela-verdade que descreve o somador completo. Desta<br />

tabela, são obtidas as equações 3.3 e 3.4 para as saídas do somador.<br />

Tabela 3.2: Tabela-verdade do somador completo (full adder).<br />

V E1 A 1 B 1 V A1 S 1<br />

0 + 0 + 0 = 0 0<br />

0 + 0 + 1 = 0 1<br />

0 + 1 + 0 = 0 1<br />

0 + 1 + 1 = 1 0<br />

1 + 0 + 0 = 0 1<br />

1 + 0 + 1 = 1 0<br />

1 + 1 + 0 = 1 0<br />

1 + 1 + 1 = 1 1<br />

S 1 = V E1 ⊕ (A 1 ⊕ B 1 ), (3.3)<br />

A equação 3.4 pode ainda ser reescrita como<br />

V A1 = A 1 · B 1 + V E1 · (A 1 + B 1 ). (3.4)<br />

o que conduz ao circuito esquematizado na figura 3.7.<br />

V A1 = A 1 · B 1 + V E1 · (A 1 ⊕ B 1 ), (3.5)<br />

3.4.3 Somador ripple carry<br />

Para somarmos números com dois ou mais bits podemos utilizar o somador completo<br />

obtido anteriormente e conectarmos os mesmos em cascata (um seguido do outro). Por<br />

45


Figura 3.7: Diagrama esquemático do somador completo.<br />

Figura 3.8: Diagrama de um somador ripple carry de 4 bits.<br />

exemplo, para somarmos dois números (A + B) de quatro bits, montamos a estrutura<br />

mostrada na figura 3.8.<br />

No primeiro somador (de ordem 0, bit menos significativo) temos que fazer V 0 = 0 pois<br />

não temos nenhum bit vindo de uma etapa anterior. Poderia também ter sido utilizado o<br />

meio-somador para essa primeira etapa, já que ele não possui essa entrada de “vem-um”.<br />

A saída “vai-um” de um somador de ordem n é conectada na entrada “vem-um” de<br />

um somador de ordem n+1. Daí a origem do nome ripple carry, o “vai-um” (carry) vai<br />

se propagando, a partir do primeiro somador (bit 0), até o último somador (bit mais<br />

significativo).<br />

Isso torna esse somador lento, já que o sinal V 4 (o “vai-um” do último somador) deve<br />

aguardar o sinal V 3 , que por sua vez tem que aguardar o sinal V 2 e assim por diante.<br />

Supondo que o atraso (tempo para que o sinal de saída se estabilize após uma variação<br />

no sinal de entrada) de cada etapa seja de t, o sinal V 4 só estará estável após um tempo<br />

de 4t. Para somadores de maior ordem (8, 16, 32 bits) esse atraso crescerá linearmente.<br />

3.4.4 Somador com “vai-um” antecipado (carry look ahead)<br />

Ao invés de esperar com que o sinal de “vai-um” (carry) se propague por todas as<br />

etapas até a última e dado que os bits dos dois números a serem somados já estão estáveis<br />

na entrada, pode-se estimar com antecedência o valor que a saída “vai-um” terá em cada<br />

etapa.<br />

Tomando por base a equação do sinal “vai-um” obtida no somador completo,<br />

podemos escrever: V i+1 = A i · B i + V i · (Ai ⊕ Bi) ⇒ V i+1 = G i + P i · V i , onde G i = A i · B i<br />

é designado generate carry e P i = (A i ⊕ B i ) é designado propagate carry. Assim, temos:<br />

46


⎧<br />

⎪⎨<br />

⎪⎩<br />

V 1 = G 0 + P 0 · V 0<br />

V 2 = G 1 + P 1 · V 1 = G 1 + P 1 · G 0 + P 1 · P 0 · V 0<br />

(3.6)<br />

V 3 = G 2 + P 2 · V 2 = G 2 + P 2 · G 1 + P 2 · P 1 · G 0 + P 2 · P 1 · P 0 · V 0<br />

V 4 = G 4 + P 3 · V 3 = G 3 + P 3 · G 2 + P 3 · P 2 · G 1 + P 3 · P 2 · P 1 · P 0 · V 0<br />

Os sinais S i ’s, por sua vez, podem ser obtidos a partir dos sinais P i ’s gerados:<br />

S i = V i ⊕ (A i ⊕ B i ) = V i ⊕ P i . (3.7)<br />

A figura 3.9 ilustra um somador de 4 bits com “vai-um” antecipado.<br />

Figura 3.9: Diagrama de um somador de 4 bits com “vai-um” antecipado.<br />

Note que o último sinal de “vai-um” (V 4 ) exigiria em seu cálculo um tempo dado pelo<br />

atraso da operação OU-Exclusivo (XOR) utilizada nos P i ’s (enquanto isso os Gi’s também<br />

estariam sendo calculados), mais o atraso da operação E (AND) entre os P i ’s calculados<br />

e finalmente o atraso da operação OU (OR). Esse tempo é praticamente igual ao tempo<br />

que o somador completo leva para gerar em sua saída os sinais de soma e “vai-um”. Dessa<br />

forma, o tempo de resposta desse somador é equivalente ao de apenas uma etapa do<br />

somador anterior (ripple carry).<br />

Note ainda que a adição de mais etapas não altera o tempo de resposta desse somador<br />

já que os sinais V i ’s levam o mesmo tempo para serem calculados.<br />

Entretanto, a adição de mais etapas torna a lógica combinacional desse somador extremamente<br />

complexa. Assim, os somadores que utilizam esse esquema fazem uso de<br />

“módulos” de 4 bits ligados em uma estrutura hierárquica. Cada módulo deve gerar os<br />

sinais G G e P G , generate group e propagate group, respectivamente. Esses dois sinais nada<br />

mais são do que o sinal V 4 desmembrado, sendo calculados como:<br />

G G = G 3 + P 3 · G 2 + P 3 · P 2 · G 1 + P 3 · P 2 · P 1 · G 0 , e (3.8)<br />

P G = P 3 · P 2 · P 1 · P 0 . (3.9)<br />

A seguinte figura ilustra o diagrama de blocos de um somador carry look ahead de 16<br />

bits:<br />

47


Figura 3.10: Diagrama de um somador de 16 bits com “vai-um” antecipado.<br />

A lógica combinacional utilizada nesse somador de 16 bits é a mesma utilizada em<br />

cada um dos somadores de 4 bits.<br />

3.4.5 Subtrator<br />

Para construirmos um subtrator podemos aproveitar uma das propriedades das portas<br />

XOR (OU-Exclusivo) de atuar como um inversor controlado e que uma subtração pode<br />

ser efetuada através de uma soma se o número a ser subtraído estiver representado em<br />

complemento de 2: A − B = A + (−B) = A + (B + 1) = A + B + 1.<br />

O circuito abaixo pode somar ou subtrair dois números de 4 bits de acordo com o sinal<br />

de controle C. Se C = 0, temos S = A + B e se C = 1, S = A − B (e despreza-se o<br />

“vai-um” final).<br />

Figura 3.11: Diagrama de um somador-subtrator de 4 bits.<br />

3.5 Matrizes esparsas<br />

Matrizes esparsas são aquelas que possuem uma grande quantidade de elementos iguais<br />

a zero. Esse tipo de matriz pode ser mais eficientemente armazenada se apenas os elementos<br />

diferentes de zero forem guardados.<br />

Existem diversos métodos para efetuar esse armazenamento [63][19]. Nesses esquemas,<br />

os elementos diferentes de zero são armazenados de forma contínua na memória e,<br />

48


dependendo do método adotado, também uma limitada quantidade de zeros. Isto, é claro,<br />

requer uma forma de saber como os elementos armazenados se encaixam na matriz completa.<br />

Essas diversas formas de armazenamento também permitem que operações sobre<br />

matrizes (soma, multiplicação) sejam efetuadas diretamente sobre a matriz reduzida, sem<br />

a necessidade de se restaurar a matriz completa.<br />

3.5.1 Compressed Row Storage (CRS)<br />

É o método mais geral de armazenamento junto com o CCS. Ele não efetua nenhuma<br />

suposição acerca da estrutura da matriz esparsa, mas também não armazena nenhum<br />

elemento desnecessário. Por outro lado, não é muito eficiente, precisando de passos adicionais<br />

(endereçamento indireto) quando se efetuam operações (multiplicação de matrizes,<br />

por exemplo) sobre a forma reduzida obtida.<br />

Dada uma matriz A i,j esparsa e assimétrica, definimos nnz como a quantidade de<br />

elementos diferentes de zero em A. Nesse método, são criados 3 vetores: val, col ind<br />

e lin ptr. O vetor val, com comprimento igual a nnz, contém os elementos diferentes<br />

de zero da matriz A, na seqüência em que aparecem em cada linha, linha por linha. O<br />

vetor col ind guarda um índice da coluna na qual se encontra cada elemento armazenado<br />

em val (se val(k) = A i,j , então col ind(k) = j). Dessa forma, col ind possui o mesmo<br />

comprimento que val. Finalmente, o vetor lin ptr armazena a posição dos elementos em<br />

val que iniciam uma nova linha e possui um comprimento igual ao número de linhas da<br />

matriz mais 1.<br />

A economia de espaço obtida por esse esquema é razoável se houver uma grande<br />

quantidade de zeros na matriz esparsa. Supondo uma matriz quadrada, ou seja, i = j = n,<br />

ao invés de serem armazenados n 2 elementos, são necessários 2nnz + n + 1 elementos.<br />

Como um exemplo, considere-se a matriz 5x5 dada por:<br />

nesse caso, tem-se:<br />

⎛<br />

A =<br />

⎜<br />

⎝<br />

10 0 0 −2 0<br />

3 9 0 0 3<br />

0 7 8 0 0<br />

4 0 0 8 0<br />

0 4 0 2 1<br />

⎞<br />

; (3.10)<br />

⎟<br />

⎠<br />

val = [ 10 −2 3 9 3 7 8 4 8 4 2 1 ] , (3.11)<br />

col ind = [ 1 4 1 2 5 2 3 1 4 2 4 5 ] e (3.12)<br />

lin ptr = [ 1 3 6 8 10 13 ] . (3.13)<br />

49


3.5.2 Compressed Column Storage (CCS)<br />

Esse método é idêntico ao CRS, exceto que as colunas de A são armazenadas ao invés<br />

das linhas. Em outras palavras, o formato CCS é igual ao CRS aplicado em A t .<br />

Similarmente ao CRS, são criados 3 vetores: val, lin ind e col ptr, onde val armazena<br />

os elementos diferentes de zero de A, lin ind é um índice das linhas na qual se encontram<br />

os valores guardados em val e col ptr indica qual elemento de val inicia uma nova coluna.<br />

Para a mesma matriz A exemplificada na descrição do método CRS, obtemos:<br />

val = [ 10 3 4 9 7 4 8 −2 8 2 3 1 ] , (3.14)<br />

lin ind = [ 1 2 4 2 3 5 3 1 4 5 2 5 ] e (3.15)<br />

col ptr = [ 1 4 7 8 11 13 ] . (3.16)<br />

3.5.3 Compressed Diagonal Storage (CDS)<br />

Se a matriz esparsa concentrar os valores diferentes de zero em uma faixa em torno de<br />

sua diagonal principal, então é mais interessante aproveitar essa estrutura no esquema de<br />

armazenagem.<br />

No CDS, as subdiagonais da matriz esparsa são armazenadas em posições consecutivas<br />

de memória, não sendo necessários os vetores de identificação de linha e coluna. A matriz<br />

reduzida obtida é também mais eficiente nas operações de multiplicação.<br />

Entretanto, nesse esquema podem ser armazenados alguns elementos iguais a zero da<br />

matriz original. Além disso, o formato CDS irá introduzir alguns zeros na matriz reduzida<br />

que nem fazem parte da matriz esparsa, mas necessários para identificar a posição original<br />

dos elementos armazenados.<br />

Aplicando o CDS na matriz assimétrica e esparsa dada por<br />

obtemos:<br />

⎛<br />

A =<br />

⎜<br />

⎝<br />

10 −3 0 0 0<br />

3 8 2 0 0<br />

0 4 9 7 0<br />

0 0 0 6 1<br />

0 0 0 5 2<br />

⎞<br />

, (3.17)<br />

⎟<br />

⎠<br />

val(−1) = [ 0 3 4 0 5 ] , (3.18)<br />

val(0) = [ 10 8 9 6 2 ] e (3.19)<br />

50


3.5.4 Jagged Diagonal Storage (JDS)<br />

val(1) = [ −3 2 7 1 0 ] . (3.20)<br />

Esse formato é bastante útil na implementação de métodos iterativos em processadores<br />

paralelos ou vetoriais. Similarmente ao CDS, os vetores obtidos possuem o mesmo comprimento<br />

da matriz esparsa. Se os valores diferentes de zero não estiverem bem concentrados<br />

em torno da diagonal principal, o JDS é mais espaço-eficiente do que o CDS.<br />

Para se obter a matriz reduzida, na forma simplificada do JDS, os elementos diferentes<br />

de zero são deslocados para a esquerda e depois as colunas são armazenadas de forma<br />

consecutiva na memória. Como as colunas podem não ter o mesmo tamanho, alguns zeros<br />

são inseridos para que todos os vetores resultantes possuam o mesmo comprimento. Após<br />

essas transformações na matriz original, são obtidos os vetores contendo os elementos<br />

diferentes de zero e os zeros inseridos (val) e os índices das colunas na qual os elementos<br />

pertenciam antes da transformação (col ind).<br />

Como um exemplo, temos:<br />

⎛<br />

A =<br />

⎜<br />

⎝<br />

10 0 −3 0 0<br />

3 0 8 2 0<br />

1 4 9 7 0<br />

0 0 0 6 1<br />

0 0 5 0 2<br />

⎞<br />

⎛<br />

→<br />

⎟ ⎜<br />

⎠ ⎝<br />

10 −3<br />

3 8 2<br />

1 4 9 7<br />

6 1<br />

5 2<br />

⎞<br />

⎛<br />

→<br />

⎟ ⎜<br />

⎠ ⎝<br />

10 −3 0 0<br />

3 8 2 0<br />

1 4 9 7<br />

6 1 0 0<br />

5 2 0 0<br />

⎞<br />

, (3.21)<br />

⎟<br />

⎠<br />

sendo obtidos:<br />

⎧<br />

⎪⎨<br />

⎪⎩<br />

⎧<br />

⎪⎨<br />

⎪⎩<br />

val(1) = [ 10 3 1 6 5 ]<br />

val(2) = [ −3 8 4 1 2 ]<br />

val(3) = [ 0 2 9 0 0 ] e (3.22)<br />

val(4) = [ 0 0 7 0 0 ]<br />

col ind(1) = [ 1 1 1 4 3 ]<br />

col ind(2) = [ 3 3 2 5 5 ]<br />

col ind(3) = [ 0 4 3 0 0 ] . (3.23)<br />

col ind(4) = [ 0 0 5 0 0 ]<br />

Fica claro que esse método não é muito eficiente se a quantidade de zeros não for<br />

grande ou se as linhas da matriz esparsa não possuírem praticamente a mesma quantidade<br />

de elementos diferentes de zero.<br />

51


Capítulo 4<br />

DESCRIÇÃO DA IMPL<strong>EM</strong>ENTAÇÃO<br />

4.1 Aplicação de Estruturas Paralelas na comparação<br />

de seqüências<br />

Para a comparação de seqüências baseadas no algoritmo de Needleman e Wunsch,<br />

as soluções computacionais seqüenciais não oferecem um bom desempenho, mesmo com<br />

processadores mais velozes, pois este algoritmo tem complexidade de tempo quadrática,<br />

conforme visto no capítulo 2. Portanto, a computação paralela tem sido empregada na<br />

tentativa de reduzir o tempo de execução desses algoritmos.<br />

Com n processadores paralelos, é possível aumentar a velocidade de processamento<br />

por um fator n, desde que o algoritmo estritamente seqüencial usado possa ser reescrito<br />

por operações paralelas simultâneas. Como a comparação de seqüências é baseada em<br />

computações análogas para cada posição de um vetor linear, pode-se conjecturar que<br />

algoritmos paralelos mais eficientes possam ser elaborados para problemas de comparação<br />

de seqüências.<br />

Existem basicamente duas formas de aplicar paralelismo ao problema de comparação<br />

de seqüências [34]:<br />

• Paralelizando a operação de comparação: neste caso, todos os processadores cooperam<br />

para determinar o escore de cada célula da matriz de similaridades. Como a<br />

granularidade é mais fina, o número de comunicações é maior;<br />

• Paralelizando o processo de comparação: neste caso, cada processador realiza um<br />

número de comparações de forma independente, ou seja, calcula o escore das células<br />

de porções menores das seqüências comparadas. Como a granularidade é mais grossa,<br />

as demandas de comunicação são reduzidas. No entanto, o desempenho dependerá<br />

de quão balanceada estiver a distribuição da carga de trabalho.<br />

O segundo método é o método mais utilizado, porém o primeiro método é mais apropriado<br />

para computadores SIMD onde todos os processadores executam a mesma instrução<br />

ao mesmo tempo, e a velocidade de comunicação é rápida quando comparada à de processamento.<br />

Sistemas SIMD geralmente possuem centenas de processadores lentos, mas<br />

52


com baixo custo de comunicação. Essa é um tipo de arquitetura na qual as estruturas<br />

sistólicas se encaixam totalmente.<br />

O segundo método é mais adequado para MIMD, onde cada processador é significativamente<br />

mais poderoso que um processador SIMD, e os processadores executam suas<br />

instruções de forma independente, em vez de cooperarem para comparar cada seqüência<br />

do banco de dados.<br />

4.2 Dependência de Dados<br />

Pela relação de recorrência do algoritmo de Smith-Waterman com penalidade constante<br />

para os espaços (equação 2.4), pode-se observar que podemos computar s i,j se s i,j−1 ,<br />

s i−1,j−1 e s i−1,j tiverem sido computados. Assim, o cálculo do valor de cada célula da<br />

matriz de similaridades depende apenas da célula da linha e coluna anteriores (mesma<br />

diagonal), da célula da mesma linha e coluna anterior (célula à esquerda) e da célula da<br />

linha anterior e mesma coluna (célula acima).<br />

Uma forma de paralelizar o cálculo da matriz respeitando-se essas dependências de<br />

dados é calcular antidiagonal por antidiagonal, uma vez que elementos em uma antidiagonal<br />

só dependem das antidiagonais previamente calculadas. A esse tipo de computação<br />

paralela dá-se o nome de computação em onda [69] (figura 4.1).<br />

Figura 4.1: Paralelização do cálculo da matriz de similaridade.<br />

4.3 Plataforma Utilizada<br />

Para o desenvolvimento do projeto foi utilizada a placa APEX PCI Development Board<br />

do fabricante Altera, contendo o FPGA APEX EP20K400EFC672. Essa placa está instalada<br />

em um computador da Dell com processador Pentium IV. A ferramenta de síntese<br />

adotada foi o Quartus II da própria Altera.<br />

4.4 Descrição Geral<br />

A implementação realizada neste trabalho foi baseada no algoritmo de comparação local<br />

de duas seqüências proposto por Smith-Waterman, utilizando a equação de recorrência<br />

com penalidade constante para os espaços (equação 2.4), conforme descrito no capítulo 2.<br />

53


Seja comparar e obter os melhores alinhamentos de duas seqüências: a seqüência de<br />

consulta sendo CATAAGGCT e a seqüência do banco de dados sendo ACATAGGCAT.<br />

Aplicando a equação de recorrência do algoritmo de Smith-Waterman (equação 2.4) a<br />

essas seqüências, obtém-se a seguinte matriz de similaridade (figura 4.2), com a origem de<br />

cada valor indicada por uma seta. Essas setas também indicam o caminho a ser percorrido<br />

para se obter os alinhamentos. Os valores assinalados com um círculo serão posteriormente<br />

explicados.<br />

Figura 4.2: Matriz de similaridade para as seqüências ACATAGGCAT e CATAAGGCT.<br />

4.4.1 Estrutura sistólica<br />

Nas diversas implementações analisadas na revisão bibliográfica do capítulo 1, ficou<br />

claro que a melhor abordagem para paralelizar em hardware o problema da comparação<br />

de seqüências utilizando programação dinâmica era a utilização de estruturas sistólicas.<br />

A utilização de um vetor sistólico permite dois tipos de mapemanto do problema: a<br />

emulação das diagonais e a emulação das colunas (figura 4.3). No primeiro tipo, cada<br />

célula do vetor é responsável pelo cálculo de uma das diagonais da matriz. Para duas<br />

seqüências com comprimentos n e m, a matriz de similaridade irá possuir n + m − 1<br />

diagonais. Dessa forma, essa é a quantidade de células necessárias para o vetor sistólico<br />

com essa abordagem. Além disso, o vetor deve ser bidirecional e as seqüências a serem<br />

comparadas devem ser deslocadas a partir de extremidades opostas em direção ao centro<br />

do vetor.<br />

Para o segundo tipo, cada célula do vetor é responsável pelo cálculo de uma coluna<br />

da matriz de similaridade. Nesse mapeamento, o vetor pode ter o comprimento da menor<br />

54


Figura 4.3: Tipos de emulação da matriz de similaridade.<br />

das seqüências e seu sentido é unidirecional.<br />

Pelos motivos expostos, a estratégia adotada foi a construção de uma estrutura<br />

sistólica linear unidirecional. Nessa abordagem, de acordo com o exposto, cada elemento<br />

de processamento do vetor sistólico é responsável pelo cálculo de uma das colunas<br />

da matriz de similaridade. A principal razão para a escolha feita é que o tamanho da<br />

estrutura (quantidade de elemento de processamento) depende apenas da seqüência de<br />

consulta, não dependendo da seqüência do banco de dados, podendo essa ter qualquer<br />

tamanho (na verdade, a memória do sistema é que irá limitar o tamanho da seqüência do<br />

banco de dados).<br />

Conforme já discutido no capítulo 1, o paralelismo obtido com a utilização de uma<br />

estrutura linear sistólica reduz a complexidade de tempo do algoritmo de Smith-Waterman<br />

de O(n × m) para O(n + m), ou seja, transforma-se um tempo quadrático em linear.<br />

Para implementar o vetor sistólico, a cada base da seqüência de consulta deve corresponder<br />

um elemento de processamento. Com isso, a seqüência de consulta pode ficar<br />

armazenada dentro do vetor. Já a seqüência proveniente do banco de dados é deslocada,<br />

da esquerda para a direita, para dentro da estrutura sistólica de forma a atravessá-la. A<br />

cada ciclo de relógio, as bases da seqüência do banco de dados deslocam uma posição e o<br />

cálculo de uma antidiagonal da matriz de similaridade é efetuado segundo o esquema da<br />

figura 4.4.<br />

Para o exemplo anterior, cuja seqüência de consulta é CATAAGGCT e a seqüência do<br />

banco de dados é ACATAGGCAT, a estrutura sistólica resultante seria:<br />

Note que a seqüência proveniente do banco de dados entra no vetor sistólico de maneira<br />

invertida, de modo que o primeiro elemento dessa seqüência possa ser comparado com o<br />

primeiro elemento da seqüência de consulta.<br />

Elemento de processamento do vetor sistólico<br />

Uma estrutura sistólica é composta por inúmeras instâncias de uma unidade menor<br />

55


Figura 4.4: Estrutura linear sistólica uniderecional.<br />

conhecida como elemento de processamento. Essas unidades são responsáveis por todo<br />

o processamento efetuado dentro do sistema sistólico. Assim, o correto planejamento<br />

dessas unidades é de vital importância para que a estrutura sistólica obtida possa ter o<br />

desempenho e a simplicidade esperada.<br />

Critérios utilizados<br />

Para o projeto dos elementos de processamento (células) da estrutura sistólica foram<br />

inicialmente estabelecidos os seguintes critérios que eles deveriam atender:<br />

i. conseguirem aplicar a equação de recorrência (equação 2.4) do algoritmo de Smith-<br />

Waterman;<br />

ii. serem o mais simples possível para que utilizem poucos recursos da FPGA e, com<br />

isso, caibam uma quantidade maior de células dentro do dispositivo. Assim, se<br />

houver duas ou mais possibilidades de implementar um mesmo circuito, o mais<br />

simples será o escolhido em relação ao mais rápido, desde que o impacto não seja<br />

grande na performance;<br />

iii. possuírem uma memória local para armazenar temporariamente os cálculos efetuados.<br />

Mais tarde, verificou-se que somente esses critérios não eram suficientes e um acréscimo<br />

foi feito a essa lista:<br />

i. conseguirem aplicar as estratégias para minimizar a utilização da memória interna<br />

(essas estratégias serão analisadas posteriormente);<br />

ii. prover mecanismos de entrega dos dados calculados e armazenados para uma memória<br />

externa.<br />

56


Foi feita uma descrição inicial em VHDL do elemento de processamento baseada nos<br />

critérios iniciais (i, ii e iii) com enfoque principal no critério ii. Posteriormente, adequou-se<br />

o elemento de processamento para que os critérios iv e v também pudessem ser atendidos.<br />

Estrutura interna<br />

De acordo com a equação 2.4, o cálculo do valor de cada célula da matriz de similaridades<br />

depende apenas da célula da linha e coluna anteriores (mesma diagonal), da célula<br />

da mesma linha e coluna anterior (célula à esquerda) e da célula da linha anterior e mesma<br />

coluna (célula acima). Dessa forma, para que essa equação possa ser aplicada dentro do<br />

elemento de processamento, esses três valores devem estar presentes dentro da célula no<br />

instante do cálculo.<br />

Foi notado que o elemento de processamento necessitava armazenar apenas o valor da<br />

diagonal e da linha superior. O valor da coluna à esquerda viria da célula adjacente como<br />

resultado do cálculo feito no ciclo de relógio anterior. A estrutura inicial do elemento de<br />

processamento pode ser vista na figura 4.5.<br />

Figura 4.5: Estrutura interna inicial do elemento de processamento.<br />

A seqüência de consulta está armazenada no vetor sistólico, com cada célula desse vetor<br />

correspondendo a uma base dessa seqüência (B C ). Em um dado momento, após um ciclo<br />

de relógio, uma nova base da seqüência do banco de dados (B BD ) entra no elemento de<br />

processamento, proveniente da célula adjacente à esquerda. Essa célula também fornece<br />

o valor da coluna à esquerda (c). Nesse mesmo instante, os valores da diagonal (a) e da<br />

linha superior (b) também estão armazenados no elemento de processamento, após terem<br />

sido gerados internamente e guardados no mesmo pulso de relógio que deslocou a base da<br />

seqüência do banco de dados para dentro da célula.<br />

Com isso, o elemento de processamento possui em seu interior todos os requisitos para<br />

aplicar a equação de recorrência do algoritmo. O novo valor calculado (d) da matriz de<br />

similaridade é fornecido para uma memória externa e ao mesmo tempo serve como base<br />

para um novo cálculo que será feito por sua célula vizinha à direita.<br />

Fluxo dos dados em seu interior<br />

57


A dinâmica de como esses dados são gerados pode ser melhor visualizada com o auxílio<br />

da figura 4.6. Para simplificar a análise, o valor fornecido pela célula adjacente à esquerda<br />

foi colocado dentro do elemento de processamento, ao lado da base da seqüência do banco<br />

de dados (G2).<br />

Figura 4.6: Fluxo interno dos dados dentro do elemento de processamento.<br />

No instante t, conforme descrito anteriormente, a célula de processamento possui todos<br />

os elementos necessários para o cálculo de um novo valor da matriz de similaridade (esse<br />

valor é calculado por intermédio de uma lógica combinacional a ser explicada). Após o<br />

pulso de relógio, instante t + 1, o dado recebido da célula adjacente à esquerda (2) passa<br />

a ser o novo valor diagonal do elemento de processamento. O valor calculado dentro do<br />

elemento de processamento (0) passa a ser o novo valor da linha superior e também segue<br />

junto com a base da seqüência do banco de dados (G) para a célula da direita. Ainda nesse<br />

instante, a base da seqüência do banco de dados que estava na célula adjacente à esquerda<br />

(A) é deslocada para o interior do elemento de processamento em questão, juntamente<br />

com o valor calculado nessa célula (1), que será o novo valor da coluna à direita.<br />

A figura 4.7 (baseada no trecho final da matriz de similaridade da figura 4.2) ilustra<br />

essa dinâmica para várias células de processamento, mostrando o fluxo dos dados dentro<br />

do vetor sistólico.<br />

Figura 4.7: Dinâmica do sistema para vários elementos de processamento.<br />

Note que a saída da última célula do vetor sistólico não é utilizada por nenhuma outra<br />

célula. Entretanto, essa saída contém uma base da seqüência do banco de dados e o último<br />

valor calculado para a linha dessa base. Assim, para o exemplo em questão, teríamos o<br />

seguinte resultado a cada pulso de relógio: C3, A4 e T4. Veremos posteriormente que essas<br />

saídas irão permitir ligar duas implementações em cascata (a saída de uma alimentando a<br />

entrada da outra) permitindo que seqüências de consulta maiores possam ser utilizadas.<br />

58


Lógica combinacional<br />

Para a lógica combinacional que calcula o novo valor da matriz de similaridade dentro<br />

do elemento de processamento, várias abordagens foram testadas para que ela ficasse o<br />

menor e mais simples possível.<br />

Na aplicação da equação de recorrência (equação 2.4), valores fixos (1, −1 e −2) são<br />

somados aos valores armazenados na célula. Como essas operações devem ser efetuadas<br />

em paralelo, mais de um somador é necessário, não sendo possível o reaproveitamento de<br />

um único somador.<br />

Além disso, os resultados parciais obtidos devem ser comparados para a obtenção de<br />

um novo valor para a matriz de similaridade. Assim, as principais operações feitas na<br />

aplicação da equação de recorrência são somas e comparações, devendo essas operações<br />

serem tratadas de forma mais minuciosa.<br />

Somadores e comparadores<br />

Um somador que “incorporasse” a constante a ser utilizada seria mais simples que<br />

um somador genérico. A desvantagem dessa estratégia é que o circuito gerado, embora<br />

mais simples, ficaria restrito. Para um outro esquema de pontuação para a equação de<br />

recorrência, uma nova descrição do somador teria que ser feita.<br />

Das abordagens clássicas de somadores vistas no capítulo 3, o somador carry look ahead<br />

foi descartado devido à sua complexidade combinacional. Assim, preferiu-se optar pelo<br />

somador ripple carry já que a quantidade de bits a serem somados não seria grande e,<br />

principalmente, pelo critério ii . O primeiro teste, somador com a constante embutida,<br />

foi feito utilizando a constante −2 em sua notação em complemento de 2 com 8 bits:<br />

111111110 (na ordem B 7 B 6 B 5 . . . B 0 ). Para o bit 0 do somador de 8 bits, pode ser utilizado<br />

o meio somador pois não temos o sinal de “vem-um”. Pela tabela-verdade do meio somador<br />

analisada no capítulo 3 (com o bit A n dessa tabela vindo do valor armazenado na célula<br />

de processamento e o bit B 0 da constante −2), sendo o bit B 0 sempre igual a zero, uma<br />

rápida observação nos leva ao seguinte resultado: S 0 = A 0 e V A0 = 0.<br />

Como V A0 = 0, a tabela-verdade do meio somador pode ser novamente utilizada para<br />

o segundo bit desse somador. Sendo o valor de B 1 = 1, temos a seguinte simplificação:<br />

S 1 = Ā1 e V A1 = A 1 .<br />

Para os demais bits do somador (S 2 a S 7 ), teremos o valor de B N sempre igual a 1.<br />

Assim, simplificando a tabela-verdade do somador completo para essa situação, obtemos:<br />

S N = ĀN · ¯V EN + A N · V EN (não-ou-exclusivo) e V AN = A N + V EN , com N variando de 2<br />

a 7.<br />

O circuito final do somador de 8 bits com a constante −2 embutida no mesmo pode ser<br />

visto na figura 4.8. Esse circuito é bem mais simples que o demonstrado no capítulo 3. O<br />

59


último sinal de “vai-um” foi mantido para indicar se o resultado da operação foi positivo<br />

ou negativo.<br />

Figura 4.8: Somador de 8 bits com a constante -2 embutida no mesmo.<br />

Para a implementação desse somador de 8 bits em VHDL foi utilizada uma descrição<br />

estrutural. Entretanto, após descrito o elemento de processamento utilizando essa simplificação<br />

e comparando com o resultado de uma descrição em um nível mais alto (simplesmente<br />

A − 2, sendo A um vetor lógico de 8 bits), verificou-se que não houve ganho<br />

algum. A quantidade de elementos lógicos utilizados da FPGA foi a mesma para as duas<br />

abordagens, como também o atraso necessário para efetuar essa operação.<br />

Testes com as constantes +1 e −1 levaram ao mesmo resultado, ou seja, sem diferença<br />

nos recursos utilizados na FPGA.<br />

Como a ferramenta de síntese também faz uma análise lógica do sistema que está sendo<br />

descrito, a explicação para tal fato é que a ferramenta efetuou as mesmas simplificações<br />

feitas manualmente no circuito.<br />

Com os comparadores, os testes feitos também tiveram o mesmo resultado. Os projetos<br />

em nível de portas lógicas resultaram na mesma utilização de recursos que circuitos<br />

descritos em níveis mais abstratos (A = B ou A > B). Dessa forma, optou-se por fazer<br />

as implementações dos somadores e comparadores em um nível mais alto, deixando a descrição<br />

em VHDL mais genérica e permitindo que outros esquemas de pontuação possam<br />

vir a ser implementados com a simples substituição das constantes utilizadas.<br />

Além da necessidade de se otimizar o circuito dos somadores e comparadores, era<br />

também preciso otimizar a quantidade utilizada desses elementos dentro da célula de<br />

processamento. O resultado dos testes anteriores mostrou também que os comparadores<br />

são menos onerosos (menor quantidade de recursos utilizados) que os somadores. Assim,<br />

quando possível, foi dada preferência para a utilização de um comparador no lugar de um<br />

somador.<br />

No cálculo de um novo valor da matriz de similaridade, o valor da diagonal é somado<br />

com 1 ou −1 se as bases comparadas das duas seqüências forem iguais ou diferentes,<br />

respectivamente. Essas operações podem ser implementadas de duas formas, de acordo<br />

com a figura 4.9.<br />

A implementação 1 utiliza dois somadores, um comparador e um multiplexador, en-<br />

60


Figura 4.9: Cálculo do valor da diagonal.<br />

quanto que a implementação 2 utiliza um somador, um comparador e um multiplexador.<br />

Independente da quantidade de recursos internos da FPGA requerida pelo somador e<br />

comparador, a implementação 2 é mais otimizada que a 1. Entretanto, a implementação<br />

1 é um pouco mais rápida que a 2, pois no circuito 1 as somas e a comparação estão<br />

sendo feitas simultaneamente, enquanto que na implementação 2 o multiplexador tem que<br />

aguardar o resultado da comparação antes de definir qual será o valor fornecido ao somador.<br />

Como a diferença de performance é baixa e o principal critério é o da economia, o<br />

circuito 2 foi o escolhido. A esse resultado parcial, foi dado um nome interno de RES1.<br />

Já os valores da coluna anterior e da linha superior são somados com -2 e esses dois<br />

resultados, juntamente com o resultado anterior (RES1) e o 0 são comparados para definir<br />

o novo valor da matriz de similaridade. Ao invés de comparar esses quatro valores simultaneamente<br />

para selecionar o maior de todos, podemos comparar os resultados parciais<br />

dois a dois e com uma nova comparação definir o resultado final.<br />

Uma dessas comparações parciais pode ser obtida de acordo com uma das implementações<br />

mostrada na figura 4.10. A esse novo resultado parcial foi dado o nome de<br />

RES2.<br />

Figura 4.10: Cálculo do valor relativo à inserção do espaço.<br />

Novamente, a implementação 2 se mostrou mais eficiente no aspecto de utilizar recursos<br />

da FPGA, embora a 1 seja um pouco mais rápida. Como as operações RES1 e RES2 são<br />

feitas em paralelo, os atrasos das duas implementações não são somados. Além disso, a<br />

lógica combinacional de uma célula não precisa aguardar o resultado da célula anterior<br />

para efetuar o seu processamento. A cada ciclo de relógio todos os valores necessários para<br />

a aplicação da equação de recorrência estão contidos na célula. Desse modo, as operações<br />

61


RES1 e RES2 além de serem feitas em paralelo dentro de uma mesma célula, são feitas em<br />

paralelo por todas as células. Pelo exposto, a escolha das implementações mais simples<br />

para esses cálculos parciais não irá acarretar em uma perda notável na velocidade de<br />

processamento da estrutura sistólica proposta.<br />

Finalmente, para se gerar o resultado final da equação, basta comparar RES1, RES2<br />

e 0, selecionando o maior dos três valores. Isso pode ser feito com um comparador e um<br />

multiplexador. Entretanto, objetivando otimizar a saída de dados para a memória, uma<br />

outra abordagem foi escolhida.<br />

Após toda essa análise, percebe-se que o elemento de processamento é essencialmente<br />

combinacional. Os flip-flops utilizados (onde são armazenados os valores na célula de<br />

processamento) servem apenas como uma barreira temporal para que as operações possam<br />

ser efetuadas sem interferência. Assim, não foi necessário descrever uma máquina de<br />

estados [28] para controlar o fluxo do processamento, tornando a estrutura sistólica ainda<br />

mais simples.<br />

Saída para a memória externa<br />

Conforme os valores da matriz de similaridade vão sendo calculados, nas regiões onde<br />

as duas seqüências são similares, esses valores vão aumentando gradativamente. Se as<br />

duas seqüências forem praticamente iguais e com a pontuação utilizada na equação 2.4, o<br />

valor final da matriz de similaridade será bem próximo do comprimento dessas seqüências.<br />

Como as seqüências são grandes, a quantidade de bits necessária para representar esses<br />

valores também será grande. Para seqüências relativamente pequenas, com 1.000 bases,<br />

já seriam necessários 10 bits para essa representação.<br />

Com a matriz de similaridade montada, ainda é necessário efetuar um percorrimento<br />

reverso (backtracking) para se obter os alinhamentos. Nesse percorrimento, é preciso<br />

descobrir quais dos três valores adjacentes originou o dado corrente. Conforme visto no<br />

capítulo 2, a origem de cada valor da matriz pode ser identificada por um vetor, permitindo<br />

que o percorrimento reverso possa ser feito baseado nesses vetores (ou ponteiros).<br />

Como os vetores podem ser representados em um comprimento fixo, optou-se por<br />

armazená-los na memória externa ao invés dos valores calculados para a matriz, que iriam<br />

exigir uma grande quantidade de bits e que dependeriam do comprimento das seqüências<br />

comparadas. Além disso, o armazenamento do vetor acelera o processo do percorrimento<br />

reverso.<br />

A princípio, dois bits poderiam representar os três vetores possíveis. No entanto, um<br />

valor gerado na matriz de similaridade pode ter mais de uma origem. Para esgotar todas<br />

as possibilidades, a representação desses vetores deve utilizar três bits. A figura 4.11<br />

mostra como pode ser feita essa codificação.<br />

Cada bit da representação indica um sentido. Assim, um valor da matriz cuja origem<br />

62


Figura 4.11: Codificação dos vetores da matriz de similaridade.<br />

foi o elemento da diagonal, seria representado por 010, ou seja, apenas com o bit V2<br />

setado. Um valor cuja origem foi a diagonal e a linha superior seria representado por 011.<br />

Para um vetor nulo, que indicaria o final de uma seqüência, todos os bits estariam em 0.<br />

O início de um alinhamento se dá quando o valor calculado para a matriz de similaridade<br />

ultrapassa um certo limite considerado como ótimo. Como o valor calculado não está<br />

sendo mais fornecido externamente, era necessário indicar quando esse limite havia sido<br />

alcançado e/ou ultrapassado. Assim, foi adicionado um bit na estrutura de representação<br />

do vetor para essa indicação. O valor limite utilizado para indicar se um alinhamento deve<br />

ser recuperado é passado ao vetor sistólico como um parâmetro na compilação do código.<br />

Com base nessa representação, o dado gerado para a memória externa possuía inicialmente<br />

4 bits, independente do tamanho das seqüências comparadas. Posteriormente, esse<br />

tamanho teve que ser aumentado para que algumas otimizações pudessem ser efetuadas.<br />

Geração dos vetores<br />

Para saber a origem de um novo valor calculado para a matriz de similaridade era<br />

preciso efetuar alguns testes com os resultados parciais obtidos anteriormente. Até esse<br />

ponto, dois resultados parciais estavam disponíveis, RES1, originado pela aplicação da<br />

equação de recorrência ao elemento da diagonal, e RES2, originado pela aplicação da<br />

equação de recorrência ao maior valor dentre os valores da coluna à esquerda e da linha<br />

superior.<br />

Para que os bits V3, V2 e V1, representando uma seta à esquerda, uma seta diagonal<br />

e uma seta para cima, respectivamente, indicassem corretamente a origem do valor calculado,<br />

levando-se em conta que ela pode não ser única, as seguintes funções lógicas foram<br />

estabelecidas:<br />

- V1: se os resultados RES1 e RES2 forem positivos e RES1 for menor ou igual a<br />

RES2 e o valor da linha superior for maior ou igual ao da coluna à esquerda ou se<br />

RES1 for negativo e RES2 positivo e o valor da linha superior for maior ou igual ao<br />

da coluna à esquerda;<br />

- V2: se os resultados RES1 e RES2 forem positivos e RES1 for maior ou igual a<br />

RES2 ou se o resultado RES1 for positivo e RES2 negativo;<br />

- V1: se os resultados RES1 e RES2 forem positivos e RES1 for menor ou igual a<br />

RES2 e o valor da linha superior for menor ou igual ao da coluna à esquerda ou se<br />

63


RES1 for negativo e RES2 positivo e o valor da linha superior for menor ou igual ao<br />

da coluna à esquerda.<br />

Com RES1 e RES2 negativos, os bits V1, V2 e V3 serão iguais a zero, indicando um<br />

vetor nulo. Para que essas funções lógicas pudessem ser mapeadas, vários sinais lógicos<br />

(flags) tiveram que ser definidos dentro do elemento de processamento:<br />

- SIN0: ativo em 1 quando o resultado parcial RES1 é maior ou igual a zero;<br />

- SIN1: ativo em 1 quando o resultado parcial RES2 é maior ou igual a zero;<br />

- FLGD: ativo em 1 quando RES1 é maior que RES2;<br />

- FLGH: ativo em 1 quando o valor da coluna à esquerda é maior que o da linha<br />

superior;<br />

- FLGI1: ativo em 1 quando o valor da coluna à esquerda é igual ao da linha superior;<br />

- FLGI2: ativo em 1 quando os resultados parciais RES1 e RES2 são iguais.<br />

Além disso, para cada um desses sinais, também foi definido o seu complementar:<br />

NSIN0, NSIN1, NFLGD, NFLGH, NFLGI1 e NFLGI2. Alguns testes mostraram que<br />

definir um sinal complementar consumia menos recursos do que ficar negando (invertendo)<br />

o sinal original.<br />

Com a definição desses sinais, as funções lógicas dos bits V1, V2 e V3 foram mapeadas<br />

da seguinte forma:<br />

- V1: SIN0·SIN1·NFLGD·NFLGH + NSIN0·SIN1· NFLGH;<br />

- V2: SIN0 ·SIN1·FLGD + SIN0·SIN1·FLGI2 + SIN0 · NSIN1;<br />

- V3: SIN0·SIN1·NFLGD·FLGH + SIN0·SIN1· NFLGD·FLGI1 + NSIN0·SIN1· FLGH<br />

+ NSIN0 ·SIN1·FLGI1.<br />

Na definição dessas funções lógicas tomou-se o cuidado de não utilizar os sinais FLGD e<br />

NFLGD quando um dos resultados parciais RES1 e RES2 fosse negativo. Na representação<br />

em complemento de 2, um número negativo possui seu bit mais significativo em 1. Assim,<br />

um comparador binário gera resultados incorretos quando dois números de sinais opostos<br />

são comparados.<br />

Aplicando as técnicas de simplificação da álgebra de Boole [28], podemos reduzir essas<br />

funções lógicas para:<br />

- V1: SIN1 · NFLGH · (NSIN0 + NFLGD);<br />

- V2: SIN0 · (NSIN1 + FLGD + FLGI2);<br />

64


- V3: SIN1 · (NSIN0 + NFLGH) · (FLGH + FLGI1).<br />

Seleção do valor final da matriz de similaridade<br />

Quando os resultados parciais RES1 e RES2 foram obtidos, foi visto que o novo valor<br />

calculado da matriz de similaridade seria o maior dentre esses dois valores e o 0. Para<br />

essa seleção, poderia ser utilizado um comparador e um multiplexador.<br />

Acontece que um dos valores a serem selecionados é o 0. Assim, podemos “fundir” o<br />

comparador e o multiplexador e criar uma função lógica que indique se o valor de RES1<br />

deve ser o escolhido ou então RES2. Se nenhum deles for selecionado, a função lógica<br />

automaticamente irá gerar o 0 como resultado final.<br />

Dois novos sinais foram criados, MUX0 e MUX1, para selecionar os resultados parciais<br />

RES1 e RES2, respectivamente. Dessa forma, o valor final gerado pode ser obtido pela<br />

seguinte função lógica: VF = MUX0 · RES1 + MUX1 · RES2.<br />

O sinal MUX0 deve ser ativado quando os resultados RES1 e RES2 forem positivos e<br />

RES1 for maior ou igual a RES2 ou se o resultado RES1 for positivo e RES2 negativo.<br />

Já o sinal MUX1 deve ser ativado quando os resultados RES1 e RES2 forem positivos e<br />

RES1 for menor ou igual a RES2 ou se o resultado RES1 for negativo e RES2 positivo.<br />

Aproveitando os sinais de geração dos vetores, podemos definir as seguintes funções<br />

lógicas, já simplificadas, para os sinais MUX0 e MUX1:<br />

- MUX0: SIN0 ”(NSIN1 + FLGD + FLGI2);<br />

- MUX1: SIN1 ”(NSIN0 + NFLGH).<br />

Note que o sinal V2 é idêntico ao sinal MUX0 e que MUX1 representa a parte comum<br />

dos sinais V1 e V3. Por essa razão, os sinais de geração dos vetores foram redefinidos<br />

para:<br />

- V1: MUX1 · NFLGH;<br />

- V2: MUX0;<br />

- V3: MUX1 · (FLGH + FLGI1).<br />

Com a utilização dos mesmos sinais para a geração dos vetores e seleção do valor final<br />

calculado, a lógica combinacional do elemento de processamento foi bastante simplificada.<br />

Terminado o projeto inicial do elemento de processamento, várias dessas unidades<br />

foram descritas de forma a constituir o vetor sistólico do sistema. Cada uma dessas<br />

unidades ocupou, em média, 30 elementos lógicos da FPGA.<br />

No entanto, após testes iniciais para validar a solução, um novo problema tinha que<br />

ser resolvido. O sistema em questão foge aos requisitos de entrada e saída discutidos no<br />

capítulo 3.<br />

65


As estruturas sistólicas são apropriadas para tarefas computacionalmente intensas mas<br />

que possuem poucas operações de entrada e saída. A comunicação com o ambiente externo<br />

ao sistema sistólico deveria ocorrer apenas nas células das bordas da estrutura.<br />

O vetor sistólico proposto foge a essa regra pois cada célula deve se comunicar com a<br />

memória externa para que o dado gerado em seu interior possa ser armazenado. Com o<br />

crescimento desse vetor, cresce também a quantidade de células que precisam acessar a<br />

memória externa.<br />

Para uma seqüência de consulta com 1.000 bases, só a quantidade de pinos da FPGA<br />

necessários para poder escrever os valores gerados na memória já inviabilizaria o processo,<br />

fora sinais de endereço e controle. Além disso, a memória possui acesso seqüencial, não<br />

aceitando escritas em paralelo.<br />

Uma alternativa seria enfileirar os dados gerados, serializando a escrita na memória.<br />

Porém, com essa abordagem, todo o ganho obtido com a computação paralela seria perdido.<br />

Dessa forma, era necessário descobrir uma forma de compactar os valores calculados<br />

ou uma maneira de diminuir sua quantidade.<br />

4.4.2 Otimização de Utilização de Espaço e Armazenamento dos<br />

Alinhamentos<br />

O tamanho considerável que as seqüências biológicas podem ter impossibilita o armazenamento<br />

da matriz de similaridades em memória. Hirschberg [29] propôs uma implementação<br />

do algoritmo de Smith-Waterman utilizando espaço linear, aproveitando-se da<br />

própria dependência de dados existente no cálculo da matriz de similaridades, uma vez<br />

que somente os valores da linha anterior e da própria linha são necessários para o cálculo<br />

de uma determinada linha da matriz.<br />

No entanto, com essa otimização, os alinhamentos não podem ser recuperados pelo<br />

procedimento normal de backtracking, pois a matriz não é armazenada em memória. Assim,<br />

somente as coordenadas iniciais e finais de cada alinhamento são armazenadas. Dessa<br />

maneira, a adoção de outras estratégias se fez necessário.<br />

Estratégias Adotadas<br />

Conforme já discutido, pelo enorme montante de dados gerados simultaneamente, era<br />

inviável que esses dados fossem escritos diretamente na memória externa. Assim, estava<br />

claro que seria necessário descrever alguma memória interna ao vetor sistólico para armazenar<br />

temporariamente os valores calculados. Isso permitiria aplicar alguma heurística<br />

que pudesse minimizar esse armazenamento e, posteriormente, entregar a matriz reduzida<br />

para a memória externa.<br />

A primeira particularidade observada na matriz de similaridade foi a grande quantidade<br />

66


de elementos iguais a zero existentes. Devido a essa quantidade, podemos considerá-la uma<br />

matriz esparsa e aplicar uma das técnicas de armazenamento vistas no capítulo 3 para<br />

esse tipo de matriz.<br />

Entretanto, nem todos os zeros da matriz podem ser descartados. Existem dois “tipos”<br />

de zeros na matriz de similaridade: aqueles no qual os resultados parciais da equação de<br />

recorrência foram todos negativos e a constante 0 foi escolhida como o valor máximo e<br />

aqueles no qual um dos resultados parciais foi igual a zero e esse resultado tem prioridade<br />

sobre a constante 0 da equação.<br />

A figura 4.12 exemplifica esses dois tipos:<br />

Figura 4.12: Tipos de zeros existentes na matriz de similaridade.<br />

No tipo 1, a origem do valor zero calculado não foi nenhum dos três valores adjacentes<br />

(diagonal, coluna à esquerda e linha superior). Já o zero do tipo 2 teve múltiplas origens.<br />

Pela equação de recorrência, deve ser subtraído 1 do valor da diagonal caso as bases<br />

comparadas sejam diferentes. Do valor da linha superior é sempre subtraído 2. Essas<br />

duas operações resultam em zero e indicam a origem do novo valor calculado da matriz.<br />

Assim, não existe nenhum vetor saindo de um zero do tipo 1, mas podem existir um<br />

ou mais vetores saindo do zero do tipo 2. Esses zeros (tipo 2) não podem ser eliminados<br />

pois eles podem fazer parte de uma seqüência considerada boa e que resultará em um<br />

alinhamento a ser obtido.<br />

A princípio, pode parecer não muito simples diferenciar um zero do tipo 1 de um zero<br />

do tipo 2. Entretanto, os zeros do tipo 1 são os únicos elementos da matriz de similaridade<br />

que não possuem vetores saindo deles. Como a célula de processamento descrita gera o<br />

vetor indicando a origem do valor calculado, se o vetor produzido for nulo, ou seja, com<br />

os três bits V1, V2 e V3 iguais a zero, significa que o dado gerado para aquela célula foi<br />

um zero do tipo 1 e pode ser eliminado.<br />

O início de qualquer seqüência dentro da matriz ocorre quando todos os valores adjacentes<br />

(diagonal, linha superior e coluna à esquerda) ao valor a ser gerado são zeros do<br />

tipo 1 e as duas bases comparadas são iguais. Assim, todas as seqüências têm como valor<br />

inicial um 1 gerado a partir de um zero do tipo 1. Isso faz com que em um percorrimento<br />

reverso de uma seqüência considerada boa, o último elemento seja sempre um zero do tipo<br />

1. A função desse zero é servir como um marca para finalizar o percorrimento reverso.<br />

Essa função que alguns zeros do tipo 1 podem ter poderia impedir que eles fossem<br />

desprezados. Mas como toda seqüência possui o mesmo comportamento inicial, uma<br />

67


marca (flag) colocada no dado gerado para a memória externa já implicaria que duas<br />

bases iguais foram comparadas e que o valor 1 foi calculado a partir de um zero do tipo<br />

1 dando início a uma nova seqüência. A estrutura do dado fornecido à memória externa<br />

foi então modificada para que essa indicação fosse possível.<br />

Esse resultado permitiu, além de descartar os zeros do tipo 1, armazenar o primeiro<br />

dado de uma seqüência juntamente com o segundo valor dessa mesma seqüência. Como só<br />

era necessário uma marca, o primeiro valor da seqüência não precisava mais ser guardado<br />

explicitamente e poderia também ser desprezado.<br />

Ainda mais, a aplicação da equação de recorrência na primeira coluna da matriz de<br />

similaridade só resulta em zeros do tipo 1 e em valores iniciais de uma seqüência. Como<br />

esses dois valores não precisam mais serem armazenados, conclui-se que todos os dados<br />

da primeira coluna da matriz podem ser descartados.<br />

A próxima observação feita é que os elementos iguais a zero da matriz (sejam eles<br />

do tipo 1 ou 2) só podem ter setas diagonais apontando para eles. Para que essa seta<br />

exista, ou seja, o zero faça parte de uma seqüência, as duas bases da diagonal seguinte<br />

ao zero devem ser iguais. Esse fato não faz a menor diferença para zeros do tipo 1 pois<br />

eles são eliminados de qualquer forma. Entretanto, isso permite que alguns zeros do tipo<br />

2 também possam ser descartados.<br />

Quando um zero desse tipo for gerado, faz-se uma “verificação antecipada” para saber<br />

se esse zero fará parte de uma seqüência ou não. Isso é possível testando as duas bases que<br />

serão utilizadas na geração do próximo valor da matriz de similaridade que se localiza na<br />

diagonal seguinte a esse zero. Se elas forem iguais (situação 1), o zero fará parte de uma<br />

seqüência e deve ser guardado. Se elas forem diferentes (situação 2), o zero calculado,<br />

mesmo sendo do tipo 2, pode ser eliminado.<br />

A figura 4.13 exemplifica o que foi dito acima.<br />

Figura 4.13: Verificação antecipada para saber se o zero fará parte de uma seqüência.<br />

Essa verificação antecipada é facilmente implementada. As duas bases que precisam<br />

ser testadas para decidir se o zero calculado na célula corrente deve ser descartado ou<br />

não estão presentes nas células vizinhas à esquerda e à direita. Como o elemento de<br />

processamento em questão já se comunica com essas duas células, essas duas bases podem<br />

ser fornecidas para a célula em questão e comparadas.<br />

A figura 4.14 ilustra a posição das duas bases que precisam ser comparadas no instante<br />

em que o zero é calculado.<br />

68


Figura 4.14: Posição das bases para a verificação antecipada.<br />

Com as otimizações feitas até aqui, um nova economia foi possível. No preenchimento<br />

da matriz de similaridade, é muito comum que duas bases comparadas sejam iguais e<br />

dêem início a uma nova seqüência. Na maioria dos casos, as bases comparadas da diagonal<br />

seguinte são diferentes e, assim, a seqüência “morre” prematuramente. Essas seqüências<br />

possuem o seguinte formato: 0 ← 1 ← 0, com o primeiro 0 sendo do tipo 1 e o segundo 0<br />

sendo do tipo 2, mas sem nenhuma seta chegando nele.<br />

Como o valor inicial da seqüência não é armazenado e o zero do tipo 2 sem setas<br />

chegando nele é descartado, esse tipo de seqüência é automaticamente eliminado. Essa<br />

situação pode ser observada na matriz de similaridade da figura 4.2, com as seqüências<br />

citadas em uma tonalidade mais clara.<br />

Finalmente, os valores gerados na última linha e na última coluna da matriz só precisam<br />

ser guardados se forem maiores ou iguais ao valor considerado como ótimo para uma<br />

seqüência. Como mais nenhum valor será calculado a partir desses dados, se uma seqüência<br />

não atingiu o valor ótimo, ela não precisará ser recuperada.<br />

Resumindo, as estratégias adotadas para reduzir a quantidade de dados armazenados<br />

da matriz de similaridade foram:<br />

- Zeros que não possuem setas saindo deles (tipo 1) podem ser descartados;<br />

- Zeros que possuem setas saindo deles (tipo 2) só são armazenados se sua diagonal<br />

seguinte possuir duas bases iguais;<br />

- A seqüência 0 ← 1 ← 0 não é armazenada se o último zero obedecer a regra anterior;<br />

- Não é necessário armazenar nenhum valor da primeira coluna da matriz de similaridade;<br />

- A última coluna só armazena valores iguais ou maiores que o valor ótimo.<br />

Vale ressaltar que a aplicação dessas regras não acarreta em nenhuma perda de informação,<br />

ou seja, os alinhamentos que podiam ser obtidos antes de sua aplicação continuam<br />

a ser recuperados após o uso dessas regras.<br />

A utilização dessas simplificações na matriz de similaridade da figura 4.2 faz com que<br />

apenas os elementos marcados com um círculo precisem ser armazenados. Essa matriz<br />

possui 110 elementos e apenas 28 tiveram que ser guardados.<br />

69


Vários exercícios feitos com matrizes que variaram de 4 × 4 (16 elementos) a 15 × 15<br />

(225 elementos) mostraram que a redução obtida com essa heurística ficou entre 75 e<br />

80%, ou seja, seria necessário armazenar apenas entre 20 e 25% dos valores gerados para<br />

a matriz de similaridade.<br />

Embora a redução tenha sido significativa, a quantidade de memória necessária ainda<br />

é considerável. Para uma comparação de seqüências relativamente pequenas, em torno de<br />

1.000 bases, a aplicação dessas regras reduziria a memória de 1MB para 200KB. Levandose<br />

em conta que as seqüências podem atingir centenas de milhares de bases, essa redução<br />

ainda não seria suficiente. Só para se ter uma idéia, uma comparação com seqüências de<br />

400K bases necessitaria de uma memória inicial de 160GB e que poderia ser reduzida para<br />

32 GB.<br />

Para que todas essas otimizações pudessem ser implementadas, a estrutura do dado<br />

gerado para a memória externa teve que ser bastante alterada. Três novos tipos de dados<br />

foram definidos: um que indica o início de um alinhamento (final de um percorrimento<br />

reverso) e contém duas bases alinhadas, um que indica um dado interno a um alinhamento<br />

e um último que indica que o valor ótimo foi alcançado e um percorrimento reverso poderia<br />

ser iniciado nesse ponto. A figura 4.15 ilustra o novo formato do dado a ser fornecido para<br />

a memória externa.<br />

Nessa nova estrutura, para simplificar a obtenção dos alinhamentos locais das duas<br />

seqüências, a base da seqüência do banco de dados também foi incorporada ao dado<br />

fornecido à memória externa. Com isso, os alinhamentos podem ser obtidos apenas com os<br />

dados fornecidos, sem a necessidade de se ter em memória as duas seqüências comparadas.<br />

Figura 4.15: Novo formato do dado fornecido à memória externa.<br />

4.4.3 Outras otimizações<br />

Além de todas as considerações feitas até aqui, no desenvolvimento do projeto foram<br />

notadas algumas outras particularidades do sistema.<br />

70


A célula inicial do vetor sistólico tem sempre os valores da diagonal e da coluna à<br />

esquerda iguais a 0 e o valor da linha superior será no máximo igual a 1. Aplicando a<br />

equação de recorrência com esses valores, percebe-se que o resultado parcial RES2 será<br />

sempre negativo, ou seja, nunca será o escolhido como resultado final. Dessa forma, a<br />

equação de recorrência só precisa ser aplicada ao elemento da diagonal. Como o valor da<br />

diagonal é sempre zero, só existirão dois resultados finais possíveis para essa célula: 1 se<br />

as duas bases comparadas forem iguais ou 0 caso contrário.<br />

Por ter uma lógica combinacional bastante simplificada, a célula inicial do vetor<br />

sistólico recebeu um tratamento diferenciado e foi descrita à parte.<br />

Outra observação feita é que, com os valores utilizados na pontuação da equação de<br />

recorrência, o valor máximo gerado pela célula inicial é igual a 1 (de acordo com o exposto<br />

acima), igual a 2 para a segunda célula da estrutura, igual a 3 para a terceira, assim<br />

sucessivamente, até a n-ésima célula da estrutura que terá um valor máximo calculado<br />

igual a n.<br />

Se todos os elementos de processamento fossem iguais, a sua lógica combinacional<br />

interna teria que ser prevista para o pior caso. Supondo novamente um vetor com 1.000<br />

células, o valor máximo gerado pela última célula seria igual a 1.000. Isso resultaria em<br />

somadores, comparadores e multiplexadores de 10 bits (2 1 0 = 1.024). Essa quantidade<br />

de bits para a segunda célula do vetor representaria um desperdício enorme já que ela<br />

necessitaria de apenas 2 bits.<br />

Dessa forma, o elemento de processamento foi descrito com um tamanho interno configurável.<br />

A quantidade necessária de bits para cada célula é passada como um parâmetro<br />

quando o elemento de processamento é instanciado na descrição em VHDL do vetor<br />

sistólico.<br />

71


Capítulo 5<br />

RESULTADOS<br />

Neste capítulo são apresentados os resultados obtidos a partir da implementação descrita<br />

no capítulo 4. Como essa implementação se deu apenas em nível de síntese, os<br />

resultados apresentados foram obtidos a partir de simulações feitas na ferramenta de desenvolvimento<br />

do fabricante. Entretanto, essas ferramentas fornecem resultados bastante<br />

precisos, não só em termos de funcionalidade do sistema, como também em termos de<br />

velocidade final do sistema, indicando caminhos críticos e atrasos dos sinais. Além disso,<br />

a comunicação com o ambiente externo não é crítica como em um sistema de tempo real,<br />

o que poderia prejudicar os resultados da simulação.<br />

Para a validação da arquitetura sistólica projetada não bastava apenas conhecer os<br />

alinhamentos obtidos na comparação entre duas seqüências, mas também conhecer toda<br />

a matriz de similaridade para verificar se as diversas otimizações sugeridas no capítulo 4<br />

estavam sendo feitas corretamente. Assim, os testes foram todos feitos com seqüências<br />

fictícias cuja matriz de similaridade era conhecida ou poderia ser construída facilmente.<br />

Para o teste de desempenho, vetores de diferentes tamanhos foram sintetizados e suas<br />

freqüências máximas de operação foram obtidas a partir de informações fornecidas pela<br />

ferramenta de síntese.<br />

5.1 Validação<br />

Diversos arquivos de estímulo foram criados contendo seqüências de tamanhos variados.<br />

Nas simulações feitas para a validação, limitou-se o tamanho das seqüências em 20 bases já<br />

que o tamanho da matriz de similaridade se torna considerável para comprimentos acima<br />

desse valor, dificultando bastante a análise e verificação.<br />

Como primeiro exemplo, a comparação de duas seqüências pequenas, com apenas 5<br />

bases cada, é apresentada. Nesse exemplo a base de consulta é CATAG e a base do banco<br />

de dados ATAGC. Depois, é feita uma pequena modificação na seqüência da base de<br />

dados, sendo alterada para CATGA. As matrizes de similaridade dessas duas seqüências<br />

pode ser vista na figura 5.1.<br />

Aplicando as otimizações em relação ao armazenamento da matriz vistas no capítulo 4,<br />

72


Figura 5.1: Matrizes de similaridade para as seqüências CATAG e ATAGC e para CATAG e<br />

CATGA.<br />

apenas os valores circulados devem ser guardados. Note que, no primeiro caso, a matriz<br />

possui 36 elementos mas somente 4 precisam ser salvos, ou seja, apenas 11<br />

A simulação da primeira comparação pode ser vista na figura 5.2.<br />

Figura 5.2: Comparação entre as seqüências CATAG e ATAGC.<br />

A seqüência do banco de dados, que é a entrada principal da simulação, está delimitada<br />

pelo sinal FLAG IN, lembrando que as bases foram codificadas internamente como A =<br />

00, T = 01, C = 10 e G = 11. O valor ótimo fornecido ao sistema está armazenado em um<br />

sinal interno VAL que, nesse caso, foi igual a 4. Os sinais M<strong>EM</strong>2, M<strong>EM</strong>3, M<strong>EM</strong>4 e M<strong>EM</strong>5<br />

são os valores fornecidos para a memória externa pelas colunas 2, 3, 4 e 5, respectivamente<br />

(a coluna inicial, do espaço, foi considerada como coluna 0). Conforme foi discutido no<br />

capítulo 4, a primeira coluna (primeiro caracter da seqüência) não precisa fornecer dados<br />

73


externamente.<br />

Como saída do sistema, além dos dados para a memória externa, temos ainda os sinais<br />

BASE OUT, DATA OUT, FLAG OUT (não colocado na figura) e CONTA. O sinal<br />

BASE OUT é simplesmente a base do banco de dados após atravessar o vetor sistólico.<br />

Já o sinal DATA OUT contém os valores calculados na última coluna da matriz de similaridade.<br />

Note que os valores de DATA OUT estão associados com as bases do banco de<br />

dados que estão na mesma linha. Dessa forma, para essa comparação (comparação 1 da<br />

figura 5.1), temos a seguinte seqüência de saída nos sinais BASE OUT e DATA OUT: A0,<br />

T0, A1, G4 e C2.<br />

Esse formato de saída permite dividir uma seqüência de consulta que não caiba no<br />

tamanho máximo do vetor em duas ou mais partes, ou seja, em dois ou mais vetores<br />

sistólicos. A saída do primeiro vetor seria a entrada do segundo e assim, sucessivamente.<br />

O último sinal, CONTA, é o valor de um contador interno e serve para que um programa<br />

externo que esteja recebendo os dados gerados consiga remontar a matriz de similaridade.<br />

Pela teoria de matrizes esparsas vista no capítulo 3, como a maior parte da<br />

matriz original é desprezada, é necessário fornecer mecanismos para recuperar a posição<br />

original na matriz completa de um valor armazenado na matriz reduzida. No nosso caso,<br />

a coluna pode ser obtida pelo próprio elemento que gerou o dado externo, assim, um dado<br />

lido de M<strong>EM</strong>2 é da segunda coluna e um dado lido de M<strong>EM</strong>5 pertence à quinta coluna.<br />

Para a informação da linha, utiliza-se o sinal CONTA que indica o instante no qual o dado<br />

foi gerado. No primeiro ciclo de relógio, só o valor da primeira coluna e primeira linha da<br />

matriz é calculado. No segundo ciclo de relógio, são calculados o valor da primeira coluna<br />

e da segunda linha e o valor da segunda coluna e primeira linha. No terceiro ciclo, os<br />

valores da primeira coluna e terceira linha, segunda coluna e segunda linha e da terceira<br />

coluna e primeira linha são gerados. Dessa forma, o valor lido do sinal CONTA menos a<br />

coluna indica a linha do valor lido. Por exemplo, um dado lido de M<strong>EM</strong>2 com um valor<br />

5 em CONTA indica que esse dado pertence à segunda coluna e terceira linha da matriz<br />

original. Para a numeração de linha utilizada foi desconsiderada a linha inicial de zeros da<br />

matriz, ou seja, a primeira linha é a primeira linha que contenha uma base da seqüência.<br />

Analisando os dados gerados para a memória externa pela simulação, verifica-se que<br />

M<strong>EM</strong>2 não forneceu nenhum valor, M<strong>EM</strong>3 forneceu apenas o valor 8AH, M<strong>EM</strong>4 forneceu<br />

dois valores (22H e 39H) e M<strong>EM</strong>5 apenas 5AH. A quantidade de valores gerados para a<br />

memória externa confere com os valores circulados na figura 5.1.<br />

M<strong>EM</strong>3 forneceu o resultado 8AH quando o valor de CONTA era igual a 5, ou seja,<br />

esse resultado pertence à terceira coluna e segunda linha da matriz original. Já M<strong>EM</strong>5<br />

forneceu 5AH quando CONTA continha 9, ou seja, esse elemento está localizado na quinta<br />

coluna e quarta linha da matriz original. Essas posições também conferem com o indicado<br />

na figura 5.1.<br />

Finalmente, em relação ao significado dos valores gerados, deve-se recorrer à estrutura<br />

74


apresentada na figura 4.15. Com aquela estrutura, temos o seguinte resultado:<br />

• M<strong>EM</strong>3: 8AH = 10001010B = 1 00 01 010 o percorrimento reverso deve ser feito<br />

na diagonal e foi resultado da comparação de duas bases T, além disso, duas bases<br />

A foram comparadas e são o final do percorrimento reverso (ou o início do alinhamento);<br />

• M<strong>EM</strong>4: 22H = 00100010B = 0 0x 00 010 o percorrimento reverso deve ser feito na<br />

diagonal e foi resultado da comparação de duas bases A;<br />

• M<strong>EM</strong>4: 39H = 00111001B = 0 0x 11 001 o percorrimento reverso deve ser para a<br />

linha superior e mesma coluna e a base G da seqüência do banco de dados deve ser<br />

alinhada com um espaço;<br />

• M<strong>EM</strong>5: 5AH = 01011010B = 0 1x 11 010 esse valor pode ser o ponto inicial de um<br />

percorrimento reverso, que deve ser feito na diagonal e foi resultado da comparação<br />

de duas bases G.<br />

Novamente, os resultados estão coerentes com a matriz de similaridade obtida para<br />

essa comparação.<br />

A simulação da segunda comparação da figura 5.1, agora com um valor ótimo igual a<br />

2, pode ser vista na figura 5.3.<br />

Figura 5.3: Comparação entre as seqüências CATAG e CATGA.<br />

Uma análise similar à que foi feita anteriormente mostra que os resultados gerados nesta<br />

simulação estão corretos e são compatíveis com a matriz de similaridade da comparação<br />

2 da figura 5.1.<br />

75


Conforme previsto, apenas 7 valores são gerados para a memória externa (1 de M<strong>EM</strong>2,<br />

2 de M<strong>EM</strong>3, 3 de M<strong>EM</strong>4 e 1 de M<strong>EM</strong>5). Como análise da informação fornecida por<br />

esses dados, por exemplo, o valor 5AH fornecido por M<strong>EM</strong>5 indica um possível início<br />

de percorrimento reverso (um valor maior ou igual ao valor ótimo), que o percorrimento<br />

reverso deve ser feito na diagonal e que as duas bases comparadas foram G.<br />

Como um último resultado de simulação, os valores gerados pela estrutura sistólica<br />

para a matriz de similaridade obtida pela comparação das seqüências ACATAGGCAT e<br />

CATAAGGCT (figura 4.2) são apresentados na figura 5.4. A seqüência CATAAGGCT<br />

por ser menor, foi colocada dentro do vetor sistólico e a outra seqüência (considerada como<br />

a seqüência proveniente do banco de dados) é que atravessou o vetor. Nessa simulação<br />

é possível ver o sinal FLAG OUT e como ele acompanha as bases do banco de dados na<br />

saída do vetor.<br />

Em uma rápida inspeção, verifica-se que a seqüência de saída vinda de BASE OUT e<br />

DATA OUT é igual à gerada na última coluna da matriz, ou seja, A0, C0, A0, T1, A0, G0,<br />

G0, C3, A4 e T4. Já a quantidade de valores gerados para memória externa foi 28 (2 de<br />

M<strong>EM</strong>2, 4 de M<strong>EM</strong>3, 5 de M<strong>EM</strong>4, 3 de M<strong>EM</strong>5, 4 de M<strong>EM</strong>6, 4 de M<strong>EM</strong>7, 4 de M<strong>EM</strong>8 e 2<br />

de M<strong>EM</strong>9), o mesmo valor que resultaria na contagem dos valores circulados na figura 4.2.<br />

Aparentemente M<strong>EM</strong>2 só gera um valor de saída, mas é que eles são iguais e o sinal que<br />

indica um dado válido externo e permitiria essa diferenciação não foi mostrado.<br />

Figura 5.4: Comparação entre as seqüências ACATAGGCAT e CATAAGGCT.<br />

76


5.2 Desempenho<br />

Para os testes de desempenho, vetores com diversos tamanhos foram sintetizados. Em<br />

cada uma dessas sínteses, a ferramenta de desenvolvimento analisou os caminhos críticos e<br />

os diversos atrasos (tempo que a mudança em sinal leva para gerar outros sinais estáveis)<br />

e determinou a freqüência máxima de operação do circuito. Além disso, a quantidade de<br />

elementos lógicos do FPGA utilizados por vetores de comprimentos diversos também foi<br />

obtida (tabela 5.1).<br />

Tabela 5.1: Quantidade de elementos lógicos utilizados e freqüência máxima de operação para<br />

diferentes comprimentos do vetor sistólico.<br />

Quantidade de Quantidade de Freqüência Média de elementos<br />

células no vetor elementos lógicos máxima de utilizados por célula<br />

do vetor<br />

5 146 122,49 MHz 29,2<br />

10 507 77,54 MHz 50,7<br />

15 900 70,35 MHz 60<br />

20 1292 64,94 MHz 64,6<br />

25 1758 62,63 MHz 70,32<br />

30 2222 56,45 MHz 74,06<br />

40 3204 56,27 MHz 80,1<br />

50 4403 56,1 MHz 88,06<br />

Pode-se perceber que quanto maior a quantidade de células do vetor, menor sua<br />

freqüência máxima de operação. Aparentemente, o aumento do número de células não<br />

deveria afetar a freqüência de operação do circuito. As células possuem a mesma estrutura<br />

interna e, assim, o atraso resultante da lógica combinacional contida em seu interior será<br />

o mesmo. Esses atrasos de cada célula não são somados, pois as operações internas em<br />

cada célula são executadas em paralelo dentro da estrutura. Dessa forma, o tempo que a<br />

lógica combinacional precisaria para ter um sinal estável na saída indicaria a freqüência<br />

máxima de operação do circuito. A adição de uma nova célula não alteraria esse tempo.<br />

A explicação para tal fato é que com poucas células na estrutura, elas podem ser alocadas<br />

em blocos contíguos no FPGA. Isso reduz bastante a necessidade de um roteamento<br />

interno dos sinais, reduzindo os atrasos de comunicação entre as células. Com o aumento<br />

do vetor sistólico, as células têm que ser espalhadas pelo FPGA e uma maior quantidade<br />

de estruturas de roteamento precisam ser utilizadas, aumentando o tempo de comunicação<br />

entre as células. Entretanto, esse atraso de comunicação também não é somado, e o maior<br />

atraso de roteamento (caminho crítico), juntamente com a lógica combinacional da célula<br />

é que irá definir a nova freqüência de operação do circuito. Assim, a partir de um determinado<br />

ponto, a dispersão das células no FPGA já não irá afetar a freqüência de operação<br />

pois o tempo de roteamento irá se estabilizar.<br />

77


A figura 5.5 ilustra esse comportamento assintótico da freqüência máxima de operação.<br />

Com poucas células, a freqüência de operação é fortemente afetada pelos atrasos de roteamento.<br />

Com o aumento da estrutura e o espalhamento das células no FPGA, os atrasos de<br />

roteamento passam a ser praticamente constantes (já se atingiu uma determinada distância<br />

limite entre os blocos), praticamente não afetando mais a freqüência de operação. O valor<br />

limite teórico obtido foi em torno de 56MHz.<br />

Figura 5.5: Freqüência máxima de operação x Quantidade de células do vetor.<br />

Em termos de quantidade de elementos lógicos do FPGA necessários para sintetizar<br />

vetores de diferentes comprimentos, percebe-se uma relação linear entre essas quantidades<br />

(figura 5.6), facilitando bastante estimativas de quantas células poderiam ser alocadas em<br />

um determinado FPGA.<br />

Por exemplo, para o FPGA da família APEX EP20K400EFC672 com 16.640 elementos<br />

lógicos existente na placa PCI de testes, estima-se que possam ser alocadas 180 células de<br />

um vetor sistólico em seu interior.<br />

Comparação<br />

O tempo de execução (comparação) do sistema projetado é dado pelo tempo que<br />

a seqüência do banco de dados leva para atravessar a estrutura sistólica. Assim, se a<br />

seqüência de consulta possuir n elementos e a seqüência do banco de dados possuir m<br />

elementos, a seqüência do banco de dados atravessará o vetor em m + n ciclos de relógio.<br />

78


Figura 5.6: Quantidade de elementos lógicos utilizados no FPGA x Quantidade de células do<br />

vetor.<br />

Dessa forma, podemos deduzir um fórmula que calcula o tempo de comparação entre duas<br />

seqüências:<br />

Texec = m + n<br />

f clock<br />

(5.1)<br />

Apenas para se ter uma idéia do desempenho que essa implementação em hardware<br />

poderia proporcionar, supondo que fosse possível criar um vetor sistólico sem limite de<br />

comprimento, com uma freqüência de operação de 50 MHz, teríamos os seguintes tempos<br />

(em segundos), comparados com uma implementação seqüencial e paralela desenvolvidas<br />

em [47]:<br />

79


Tabela 5.2: Comparação de velocidade entre uma implementação seqüencial, diversas paralelas<br />

e em hardware do algoritmo baseado em programação dinâmica.<br />

Tamanho das 2 4 8 Vetor<br />

Seqüências Seqüencial Processadores Processadores Processadores Sistólico<br />

15kB X 15kB 296s 283,18s 202,18s 181,29s 0,000614s<br />

50kB X 50kB 3461s 2884,15s 1669,53s 1107,02s 0,002048s<br />

80kB X 80kB 7967s 6094,19s 3370,40s 2162,82s 0,003277s<br />

150kB X 150kB 24107s 19522,95s 10377,89s 5991,79s 0,006144s<br />

400kB X 400kB 175295s 141840,98s 72770,99s 38206,84s 0,016384s<br />

Embora o desempenho exibido na tabela 5.2 ainda não possa ser alcançado, por não ser<br />

possível colocar essa quantidade de células em um FPGA considerando o atual estágio de<br />

integração, ela demonstra o enorme ganho de velocidade que uma abordagem em hardware<br />

pode proporcionar. Dessa forma, mesmo que as seqüências tenham que ser divididas em<br />

pedaços menores, de forma que cada pedaço possa ser calculado dentro do FPGA, e depois<br />

os resultados parciais reunidos de modo a produzir a solução completa, pela diferença de<br />

velocidade apresentada, essa abordagem merece ser estudada.<br />

80


Capítulo 6<br />

CONCLUSÕES<br />

O volume de informações geradas para os bancos de dados biológicos tem sido maior<br />

que o crescimento do poder de processamento das máquinas utilizadas para processar essas<br />

informações. Dessa forma, encontrar mecanismos eficientes para tratar esses dados é um<br />

desafio constante da Bioinformática.<br />

Dentre as operações necessárias para esse tratamento, uma das mais utilizadas é a<br />

comparação de seqüências. O algoritmo de Smith-Waterman, baseado em programação<br />

dinâmica, é o que produz os melhores resultados, mas apresenta complexidades quadráticas<br />

de tempo e espaço, não sendo utilizado amplamente em projetos de seqüenciamento de<br />

genomas. Os programas mais utilizados são baseados em probabilidades e heurísticas que,<br />

apesar de serem consideravelmente mais rápidos, podem omitir resultados importantes.<br />

Para tentar melhorar o desempenho dos algoritmos baseados em programação dinâmica,<br />

soluções utilizando paralelismo vêm sendo desenvolvidas, tanto em hardware quanto em<br />

software.<br />

Este trabalho mostrou como um hardware dedicado, baseado em uma estrutura sistólica,<br />

é capaz de linearizar a complexidade temporal e reduzir bastante o tempo de processamento<br />

desses algoritmos.<br />

Embora o dispositivo gerado tenha sido apenas em nível de síntese, os resultados<br />

obtidos podem ser considerados bastante confiáveis, dada a precisão que a ferramenta de<br />

síntese possui para simulações funcionais e temporais.<br />

Para que a implementação proposta se torne funcional é necessário o desenvolvimento<br />

de um programa que converta as seqüências para a codificação interna utilizada no vetor,<br />

que forneça esses dados ao vetor pelo barramento PCI e que leia os dados gerados, montando<br />

a matriz de similaridade completa ou trabalhando com a matriz reduzida para o<br />

obtenção dos alinhamentos. Dada a velocidade na qual os resultados são produzidos pelo<br />

vetor, o programa deverá possuir mecanismos de sincronização para não haver perda de<br />

dados.<br />

Esse mesmo programa poderia dividir as seqüências em vários pedaços menores e<br />

efetuar a comparação desses pedaços menores, armazenando os resultados temporários e<br />

depois montando uma solução final. Como a velocidade do hardware projetado é muito<br />

81


grande, mesmo com uma granularidade pequena, que aumenta os custos de comunicação,<br />

o desempenho final do sistema ainda deverá ser bastante satisfatório.<br />

Outra possível implementação seria utilizar as soluções propostas em [50] e [47], baseadas<br />

em [14]. Em cada um desses trabalhos foi desenvolvido um programa para paralelizar o<br />

algoritmo de Smith-Waterman e, com isso, obter um ganho de performance. O problema<br />

do cálculo da matriz de similaridade foi dividido em blocos e cada um desses blocos é<br />

enviado para um processador do cluster. O hardware aqui proposto poderia ser utilizado<br />

para o cálculo de cada um desses blocos menores. Uma placa PCI similar à utilizada nessa<br />

dissertação poderia ser colocada em cada computador do cluster que, ao receber o bloco a<br />

ser calculado, repassaria esse bloco para o vetor sistólico e armazenaria os valores gerados.<br />

Dessa forma, teríamos dois níveis de paralelismo atuando, em software e em hardware, o<br />

que poderia acelerar bastante o tempo de processamento dessas comparações.<br />

Embora nesse trabalho tenha se conseguido simplificar bastante a quantidade de dados<br />

que devem ser guardados da matriz de similaridade, o resultado obtido ainda está longe de<br />

uma condição ideal. Pela revisão bibliográfica vista no capítulo 1, pode-se notar que o alvo<br />

principal das pesquisas é proporcionar um ganho de velocidade ao algoritmo, com poucos<br />

estudos sobre otimizações de espaço. Essa otimização é extremamente importante, dada<br />

a enorme quantidade de elementos que a matriz de similaridade pode possuir. Já notando<br />

esse problema, Cuvillo [14] sugere uma heurística para guardar apenas os alinhamentos<br />

que poderiam ser considerados bons, ignorando os demais. A união das otimizações aqui<br />

propostas com as utilizadas por Cuvillo poderiam ser avaliadas, bem como a aplicação de<br />

outras técnicas que pudessem reduzir ainda mais a quantidade de dados armazenados.<br />

Outro problema também não resolvido completamente foi o fornecimento dos valores<br />

gerados pelo vetor para uma memória externa. Como vários valores podem ser gerados<br />

simultaneamente, para que eles pudessem ser escritos em uma única memória, uma serialização<br />

desses dados seria necessária. Isso acarretaria uma perda da performance obtida<br />

nos cálculos em paralelo. Entre as possíveis soluções poderia se avaliar a utilização de<br />

memórias entrelaçadas [35] e a divisão da memória em blocos. Além disso, a família<br />

APEX de FPGAs da Altera, possui facilidades para implementar memórias de conteúdo<br />

(CAM), que também poderiam ser avaliadas.<br />

Finalmente, nas simplificações manuais feitas nos somadores e comparadores percebeuse<br />

que a ferramenta de síntese gerou os mesmos resultados automaticamente. Entretanto,<br />

na definição dos sinais internos para a geração dos vetores e escolha do melhor valor para a<br />

célula, algumas simplificações manuais e algumas outras observações descritas no capítulo<br />

4 resultaram em sínteses mais otimizadas que as obtidas automaticamente. Uma análise<br />

mais aprofundada desses resultados fugia ao escopo desta pesquisa. Assim, poderia ser alvo<br />

de estudo uma metodologia que forneça mecanismos ou aponte caminhos ao projetista para<br />

que ele possa decidir que parte da descrição deve ser simplificada automaticamente e que<br />

parte requer uma análise manual mais detalhada. A possível criação de uma biblioteca de<br />

82


componentes ou unidades funcionais otimizadas que pudessem ser utilizadas em projetos<br />

de maior porte também poderia fazer parte desse estudo.<br />

83


REFERÊNCIAS BIBLIOGRÁFICAS<br />

[1] IEE standard VHDL language reference manual, IEEE std. Relatório técnico, The<br />

Institute of Electrical and Electronics Engineers, 1988.<br />

[2] Primer on Molecular Genetics. U.S. DOE — Department of Energy., 1991.<br />

[3] Initial sequencing and analysis of the human genome. Relatório técnico, The Genome<br />

International Sequencing Consortium, Fevereiro de 2001.<br />

[4] Adário, A. M. S., Bampi, S., e Jacobi, R. P. Reconfigurable architectures. volume 12,<br />

páginas 133–136, Porto Alegre: PPGC da UFRGS, 1997.<br />

[5] Adário, A. M. S., Roehe, E. L., e Bampi, S. Dynamically reconfigurable achitecture<br />

for image processor applications. Em Design Automation Conference, páginas 623–<br />

628. ACM, 1999.<br />

[6] Altschul, S. F., Gish, W., Miller, W., Myers, E. W., e Lipman, D. J. Basic local<br />

alignment search tool. Journal of Molecular Biology, 215:403–410, 1990.<br />

[7] Amabis, J. M. e Martho, G. R. Curso Básico de Biologia, volume 1. Editora Moderna,<br />

1988.<br />

[8] Amabis, J. M. e Martho, G. R. Curso Básico de Biologia, volume 2. Editora Moderna,<br />

1988.<br />

[9] Arnold, J. M., Buell, D. A., e Davis, E. G. Splash 2. ACM Symposium on Parallel<br />

Algorithms and Architectures, 1992, Junho.<br />

[10] Aschenden, P. J. The Designer´s Guide to VHDL. Morgan Kaufmann Publishers,<br />

Inc., San Francisco, CA, 1996.<br />

[11] Brutlag, D. L., Dautricourt, J. P., Maulik, S., e Relph, J. Improved sensitivity of<br />

searches of biological sequence databases. CABIOS, 6 (3):237–245, 1990.<br />

[12] Carro, L. Projeto e Prototipação de Sistemas Digitais. Editora Universidade/UFRGS,<br />

Porto Alegre, RS, 2001.<br />

[13] Cormen, T. H., Leiserson, C. E., e Rivest, R. L. Introduction to Algorithms. MIT<br />

Press: McGraw Hill, 1990.<br />

[14] Cuvillo, J. Whole genome comparison using a multithreaded parallel implementation.<br />

Dissertação de Mestrado, Universidade de Delaware, 2001.<br />

[15] Dalton, J. Absorption of gases by water and other liquids. 1803.<br />

[16] Dayhoff, M. O., Scwartz, R. M., e Orcutt, B. C. A model of evolucionary change<br />

in proteins. volume 5, páginas 345–352, Washington, DC, 1978. Natl. Biomed. Res.<br />

Foundation.<br />

[17] Cuvillo, J. B.del , Martins, W. S., Gao, G. R., Cui, W., e Kim, S. ATGC: Another<br />

tool for genome comparison. Relatório técnico.<br />

84


[18] E., M. P. R. T. D. The Verilog Hardware Description Language. Kluwer Academics<br />

Publishers, 1991.<br />

[19] Eijikhout,. Lapack working note 50: Distributed sparse data structures for linear<br />

algebra operations. Relatório técnico, Computer Science Department, University of<br />

Tennessee, Knoxville, TN, 1992.<br />

[20] Gajski, D., Dutt, N., Wu, A., e Lin, S. Sigh Level Systems – Introduction to Chip and<br />

System Design. Kluwer Academic Publishers, Massachusets, Estados Unidos, 1992.<br />

[21] Gibas, C. e Jambeck, P. Developing Bioinformatics Computer Skills. O’Reilly, 2001.<br />

[22] Gokhale, M. Splash: A reconfigurable linear logic array. Procedings of 1990 International<br />

Conference on Parallel Processing, páginas 526–532, 1990.<br />

[23] Gotoh,. An improved algorithm for matching biological sequences. J. Mol. Biol.,<br />

162:705–708, 1982.<br />

[24] Grice, J. A., Hughey, R., e Speck, D. Parallel sequence alignment in limited space.<br />

Em Proc. Int. Conf. Intelligent Systems for Molecular, páginas 145–153. AAAI/MIT<br />

Press, 16-19 de Julho de 1995.<br />

[25] Guccione, S. A. e Keller, E. Gene matching using jbits. Xilinx, Inc., 2002.<br />

[26] Hadley, J. D. e Hutchings, B. L. Design methodologies for partially reconfigured<br />

systems. páginas 78–84, Califórnia, Estados Unidos, 1995.<br />

[27] Henikoff, S. e Henikoff, J. G. Aminoacid substitution matrices from proteins blocks.<br />

volume 89, páginas 10915–19, 1992.<br />

[28] Hill, F. J. e Peterson, G. R. Computer Aided Logical Design with Emphasis on VLSI.<br />

John Wiley & Sons, Inc, 4 edição, 1993.<br />

[29] Hirschberg, D. A linear space algorithm for computing maximal common subsequences.<br />

Communications of the ACM, 18:341–343, 1975.<br />

[30] Hirschberg, J. D., Hughey, R., e Karplus, K. Krestel: A programmable array for<br />

sequence analysis. Em Proc. Int. Conf. Application-Specific Systems, Architectures<br />

and Processors, páginas 25–34. IEEE CS, 19-21 de Agosto de 1996.<br />

[31] Hoang, D. T. A systolic array for the sequence alignment problem. Relatório Técnico<br />

CS-92-22, Brown University, Providence, RI, 1992.<br />

[32] Hoang, D. T. e Lopresti, D. P. FPGA implementation of systolic sequence alignment.<br />

1992.<br />

[33] Hughes, N. Implementing sequence matching algorithms with hardware compilation.<br />

Relatório técnico, St. Hugh’s College.<br />

[34] Hughey, R. Parallel hardware for sequence comparison and alignment. CABIOS,<br />

12(6):473–479, Dezembro de 1996.<br />

[35] Hwang, K. Advanced Computer Architecture. McGraw-Hill International Editions,<br />

Nova Iorque, 1993.<br />

[36] Information Sciences Institute - East, http:// www.east.isi.edu/projects/SLAAC/.<br />

Slaac project. World Wide Web site.<br />

[37] Kung, H. T. Why systolic architectures? IEEE Computer, 15 (1):37–46, Janeiro de<br />

1982.<br />

[38] Lavenier, D. Dedicated hardware for biological sequence comparison. 1996.<br />

85


[39] Lavenier, D. SAMBA - Systolic Accelerators for Molecular Biological Applications.<br />

Relatório Técnico 988, IRISA, Março de 1996.<br />

[40] Lavenier, D. Speeding up genome computations with a systolic accelerator. SIAM<br />

News, 31(8):1–7, Outubro de 1998.<br />

[41] Lewin, B. Genes VII. Artmed, Porto Alegre, RS, Brasil, 2001.<br />

[42] Lipsett, R., Schaefer, C., e Ussery, C. VHDL: Hardware Description and Design.<br />

Kluwer Academic Press, 1989.<br />

[43] Lipton, R. J. e Lopresti, D. A systolic array for rapid string comparison. Em Chapel<br />

Hill Conference on VLSI, páginas 363–376, 1985.<br />

[44] Luscombe, N. M., Greenbaum, D., e Gerstein, M. Yearbook Of Medical Informatics<br />

2001, chapter What is bioinformatics? An introduction and overview, páginas 83–<br />

100. International Medical Informatics Association, 2001.<br />

[45] Martins, W. S., Cuvillo, J. B.del , Useche, F. J., Theobald, K. B., e Gao, G. R.<br />

A multithreaded parallel implementation of a dynamic programming algorith for<br />

sequence comparison. Relatório técnico.<br />

[46] Martins, W. S., Cuvillo, J.del , Cui, W., e Gao, G. R. Whole genome alignment using<br />

a multithreaded parallel implementation. Relatório técnico.<br />

[47] Melo, R. C. F. Comparação de seqüências biológicas utilizando dsm. Dissertação<br />

de Mestrado, Departamento de Ciência da Computação, Universidade de Brasília,<br />

Brasília, DF, Janeiro de 2003.<br />

[48] Michel, P., Lauther, U., e Duzy, P. The Synthesis Approach to Digital Systems Design.<br />

Kluwer Academic Publishers, Massachusets, Estados Unidos, 1992.<br />

[49] Michele, G. D. Synthesis and Optimization of Digital Circuits. McGraw-Hill, 1994.<br />

[50] Murakami, M. M. Uma nova abordagem para pesquisa paralela em bancos de dados<br />

biológicos utilizando algoritmos de comparação de seqüências baseados em programação<br />

dinâmica. Dissertação de Mestrado, Departamento de Ciência da Computação,<br />

Universidade de Brasília, Brasília, DF, Março de 2003.<br />

[51] Needleman, S. B. e Wunsch, C. D. A general method applicable to the search for<br />

similarities in the amino acid sequence of two proteins. volume 48, páginas 443–453,<br />

1970.<br />

[52] Splash 2, S. G. D.on . Dzung t. hoang. páginas 185–191, Los Alamitos, CA, 1993.<br />

IEEE Computer Society Press.<br />

[53] ONSA - Organization for Nucleotide Sequencing and Analysis,<br />

http://watson.fapesp.br/onsa/Genoma3.htm. Genoma3.<br />

[54] Page, I. Reconfigurable processor architectures. Microprocessors and Microsystems<br />

(Special Issue on Codesign), 20:185–196, 1996.<br />

[55] Pappas, N. P. Searching biological sequence databases using distributed adaptive<br />

computing. Dissertação de Mestrado, Virginia Polytechnic Institute and State University,<br />

Blacksburg, Virginia, Janeiro de 2003.<br />

[56] Paracel, Inc, http://www.paracel.com/. 2001.<br />

[57] Paracel Inc, http://www.paracel.com/products/pdfs/gm2 datasheet.pdf. The Genematcher2<br />

System Datasheet, 2002.<br />

[58] Patzer, A. Highly parallel DNA sequence matching and alignment processor.<br />

86


[59] Pearson, W. R. e Lipman, D. L. Improved tools for biological sequence comparison.<br />

Proceedings Of The National Academy Of Science USA, 85:2444–2448, Abril de 1988.<br />

[60] Puttegowda, K., Worek, W., Pappas, N., Dandapani, A., e Athanas, P. A run-time<br />

reconfigurable system for gene-sequence searching. Proceedings of the International<br />

VLSI Design Conference, Janeiro de 2003.<br />

[61] Rognes, T. ParAlign: a parallel sequence alignment algorithm for rapid and sensitive<br />

database searches. Nucleic Acids Research, 29(7):1647–1652, 2001.<br />

[62] Rognes, T. e Seeberg, E. Six-fold speed-up of Smith-Waterman sequence database<br />

searches using parallel processing on common microprocessors. Bioinformatics,<br />

16(8):699–706, 2000.<br />

[63] Saad,. Sparskit: A basic tool kit for sparse matrix computation. Relatório Técnico<br />

CSRD TR 1029, University of Illinois, Urbana, IL, 1990.<br />

[64] Setubal, J. C. e Meidanis, J. Computational Molecular Biology. PWS, 1997.<br />

[65] Simpson, A. J. G. The genome sequence of the plant pathogen xylella. Nature,<br />

406:151–157, Julho de 2000.<br />

[66] Smith, T. e Waterman, M. Identification of common molecular subsequences. Journal<br />

of Molecular Biology, 147:195–197, 1981.<br />

[67] TimeLogic Corp, http://www.timelogic.com. 2002.<br />

[68] TimeLogic Corp, http://www.timelogic.com/ decypher intro.html. DeCypher, 2002.<br />

[69] Trelles, O. On the parallelization of bioinformatic applications. volume 2, 2001.<br />

[70] Villasenor, J. e Amgione-Smith, W. Configurable computing. Scientific American,<br />

19:54–58, 1997.<br />

[71] Waterman, M. S. Sequence alignments. páginas 53–92. CRC Press, 1989.<br />

[72] Watson, J. D. e Crick, F. H. Molecular structure of nucleic acids: A structure for<br />

deoxyribose nucleic acid. Nature, 171:737–738, Abril de 1953.<br />

[73] White, C. T., Singh, R. K., Reintjes, P. B., Lampe, J., Erickson, B. W., Dettloff,<br />

W. D., Chi, V. L., e Altschul, S. F. Bioscan: A vlsi system based for biosequence<br />

analysis. páginas 504–509. IEEE Computer Society Press, 1991.<br />

[74] Worek, W. J. Matching genetic sequences in distributed adaptive computing systems.<br />

Dissertação de Mestrado, Virginia Polytechnic Institute and State University,<br />

Blacksburg, Virginia, Julho de 2002.<br />

[75] Xilinx, Inc., http://www.xilinx.com.<br />

[76] Yamaguchi, Y., Maruyama, T., e Konagaya, A. High speed homology search with<br />

FPGAs. Pacific Symposion on Biocomputing, páginas 271–282, 2002.<br />

[77] Yang, B. H. W. A parallel implementation of Smith-Waterman sequence comparison<br />

algorithm. Relatório Técnico ID: 4469409, Instituição, 2002.<br />

[78] Yu, C. W., Kwong, K. H., Lee, K. H., e Leong, P. H. W. A smith-waterman systolic<br />

cell. The Chinese University of Hong Kong, 2003.<br />

87

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!