You are on page 1of 9

Uma Implementao Eficiente do Quicksort Externo

Resumo. Pretende-se com este artigo apresentar uma implementao eficiente do Quicksort Externo, um algoritmo para ordenao externa in situ. Sua implementao na linguagem C comparada com softwares eficientes para ordenao externa. As mtricas utilizadas na comparao so tempo de execuo e quantidade de espao total utilizado na ordenao. Por fim, pretende-se averiguar empiricamente a sua complexidade de caso mdio levando em considerao o nmero de operaes de entrada e sada efetuadas. Palavras-chave: Ordenao externa, Quicksort Externo.

1. Introduo
Atualmente, a necessidade de ordenar grandes volumes de dados tem se tornado muito importante para grandes corporaes, instituies governamentais, bancos e outros. Como no possvel armazenar todos os dados na memria principal de um computador, mecanismos eficientes de ordenao em memria secundria, tambm conhecida como ordenao externa, devem ser utilizados. Diferentemente dos algoritmos de ordenao interna, onde a principal operao considerada na anlise dos algoritmos a comparao entre chaves, o principal objetivo em ordenao externa minimizar o nmero de operaes de entrada e sada (E/S) executadas. Isto porque o tempo para se realizar uma operao de E/S muito maior do que o tempo de uma operao da unidade central de processamento. A gerncia da quantidade de operaes de E/S executadas por um algoritmo de ordenao pode ser feita de duas formas. A primeira delas quando o algoritmo de ordenao projetado para utilizar somente a memria interna disponvel e com o objetivo de minimizar o nmero de operaes de E/S efetuadas. Em [Leu, 00], citado que o limite inferior, considerando o nmero de operaes de E/S, para se ordenar n registros dado por:

n n log b O K b log b

(I )

sendo K o nmero de registros que podem ser armazenados na memria interna; b a quantidade de registros que podem ser armazenados no bloco de leitura ou gravao do Sistema Operacional (SO). Caso K n b , o limite inferior passa a ser n O (II ) . b

Na outra abordagem de gerncia do nmero de operaes de E/S, utilizado um algoritmo de ordenao interna tradicional, tal como Quicksort [Hoare, 62] [Ziviani, 93] ou heapsort [Ziviani, 93], porm no levado em considerao que a memria interna seja limitada. Isto possvel em SOs que implementam um mecanismo de memria virtual, o qual gerencia as operaes de E/S. Nessa abordagem, para minimizar o nmero de operaes de E/S, os algoritmos devem possuir caractersticas que diminuam a quantidade de faltas de pginas no mecanismo de memria virtual. Sedgewick [Sedgewick, 83] cita que o Quicksort um bom mtodo para ser utilizado nesse ambiente, pois possui uma pequena localidade de referncia. Isto diminui o nmero de faltas de pginas em um ambiente de memria virtual. Para estudos mais detalhados sobre o Quicksort em memria virtual pode-se consultar [Verkamo, 87]. Outro fator importante diz respeito quantidade de memria extra utilizada para a ordenao externa. Basicamente, so utilizadas duas abordagens. A primeira a ordenao in place [Monard, 80], tambm conhecida como ordenao in situ. Nela, a entrada ordenada de forma que o arquivo original seja sobrescrito. O mtodo utiliza somente O(log n) unidades de memria interna, onde n o nmero de registros a serem ordenados, sendo que no necessrio nenhuma memria externa alm da que utilizada pelo arquivo original. Na outra abordagem, no h restrio quanto ao uso extra de memria interna ou externa. Na seo 2, apresentado o Quicksort Externo, um algoritmo para ordenao externa proposto por Monard [Monard, 80] que se enquadra na abordagem de ordenao in situ e utiliza uma tcnica semelhante ao Quicksort tradicional [Hoare, 62] [Ziviani, 93]. Na seo 3, o Quicksort Externo comparado com softwares que realizam eficientemente a ordenao externa. Os softwares escolhidos foram o Nitrosort [Nitrosort, 03] e o Sort. O primeiro foi escolhido por ser um produto comercial muito eficiente e o segundo por ser muito popular, j que um aplicativo presente em vrios SOs. As principais mtricas utilizadas na avaliao foram a quantidade de espao extra utilizado por cada um deles e a eficincia em termos de tempo de execuo. Apesar de no ser um dos objetivos primrios, foram realizados testes com o Quicksort tradicional fazendo uso do ambiente de memria virtual, e os resultados foram comparados com os do Quicksort Externo. Enfim, na seo 4 o artigo concludo e alguns estudos so propostos.

2. Quicksort Externo
O Quicksort Externo um algoritmo que utiliza o mtodo de diviso e conquista para ordenar in situ um arquivo A = {R1,K, Rn } de n registros armazenados consecutivamente em memria secundria de acesso randmico. Considerando que Ri, onde 1 i n , o registro que se encontra na i-sima posio de A, o primeiro passo do algoritmo particionar A da seguinte forma: {R1 ,K, Ri } Ri+1 Ri+2 K R j 2 R j 1 {R j ,K, Rn }, utilizando para isto um buffer na memria interna de tamanho K = j i + 1, com K 3 . Logo aps, o algoritmo chamado recursivamente em cada um dos subarquivos A1 = {R1,K, Ri } e A2 = {Rj ,K, Rn },

sendo que primeiramente ordenado o subarquivo de menor tamanho. Esta condio necessria para que, na mdia, o nmero de subarquivos com o processamento adiado no ultrapasse log n. Subarquivos vazios ou com um nico registro so ignorados. Caso

o arquivo de entrada A possua no mximo K registros ele ordenado em um nico passo, ou seja, cada registro do arquivo lido e escrito uma nica vez. Um pseudocdigo, obtido de Monard [Monard, 80], para o Quicksort Externo exibido abaixo:
procedure quicksort_externo(esq, dir); {esq e dir so, respectivamente, os endereos do primeiro e do ltimo registro de A} i, j: Integer; if dir - esq >= 1 then particao(esq, dir,i, j); if i - esq < dir - j then {Ordena primeiro o menor subarquivo} quicksort_externo(esq, i); quicksort_externo(j, dir); else quicksort_externo(j, dir); quicksort_externo(esq, i); end if end if end procedure Cdigo 1: procedimento do Quicksort Externo

Uma questo importante como so determinados os pontos i e j de partio do arquivo. Os valores das chaves dos registros Ri e Rj so denominados, respectivamente, limite inferior Linf e superior Lsup. O objetivo do procedimento particao chamado no Cdigo 1 copiar todos os registros menores ou iguais a Ri para A1 e todos os maiores ou iguais a Rj para A2. Inicialmente, Linf = e Lsup = + . A leitura de A controlada por dois apontadores RL (read lower) e RU (read upper), que apontam, no incio, para os extremos esquerdo e direito de A, respectivamente. Da mesma forma, a escrita em A controlada por WL (write lower) e WU (write upper). Os registros do arquivo A so lidos pelo procedimento particao, alternadamente, dos extremos de A at que K 1 registros tenham sido lidos e armazenados no buffer interno. A cada leitura no extremo esquerdo, RL incrementado de um e a cada leitura no extremo direito, RU decrementado de um. O mesmo ocorre com WL e WU quando escritas so realizadas no extremo que controlado por cada um destes apontadores. Para garantir que os apontadores de escrita estejam, pelo menos, um passo atrs dos apontadores de leitura, a ordem alternada de leitura interrompida se RL = WL ou RU = WU. Somente uma dessas condies verdadeira em um determinado instante, pois K 3 . Isto faz com que nenhuma informao seja destruda durante a ordenao do arquivo.

Ao ler o K-simo registro, sua chave C comparada com Lsup. Caso seja maior, o valor de WU atribudo a j e o registro escrito em A2. Caso contrrio, sua chave comparada com Linf; sendo menor, o valor de WL atribudo a i e o registro escrito em A1. Se Linf C Lsup , o registro inserido no buffer. Neste momento, o buffer se encontra cheio e uma deciso deve ser tomada para remover um elemento do mesmo. Esta deciso tomada levando em considerao o tamanho atual de A1 e A2 que so, respectivamente, T1 = WL esq e T2 = dir WU . Caso T1 < T2 , o registro R de menor chave CR extrado do buffer e escrito na posio apontada por WL em A1. Neste momento, o valor de Linf atualizado com o valor de CR. Caso contrrio, o registro R de

maior chave CR extrado do buffer e escrito na posio apontada por WU em A2. Neste momento, o valor de Lsup atualizado com o valor de CR. O objetivo de se tomar tal deciso sempre escrever o registro retirado do buffer no arquivo de menor tamanho. Desta forma, o arquivo original A dividido to uniformemente quanto possvel. Assim, a rvore gerada pelas chamadas recursivas de quicksort_externo ser mais balanceada, o que, como provado em Monard [Monard, 80], um dos critrios para minimizar a quantidade de operaes de E/S efetuadas pelo algoritmo. O outro critrio seria aumentar o tamanho do buffer interno. O processo de partio continua at que RL e RU se cruzem, ou seja, RU < RL. Neste instante, existiro K 1 registros no buffer interno, os quais devem ser copiados j ordenados para A. Para isto, enquanto existir elementos no buffer, o menor deles extrado e escrito na posio apontada por WL em A. Um pseudocdigo para o procedimento particao, gerado a partir do apresentado por Monard [Monard, 80], exibido no Cdigo 2. Nele, o procedimento readup l em last_read o registro apontado por RU, decrementa RU de um e atribui false a up_reading. Da mesma forma, readlow l em last_read o registro apontado por RL, incrementa RL de um e atribui true a up_reading. J o procedimento writeup(r) escreve o registro r na posio apontada por WU e decrementa WU de um. Semelhantemente, writelow(r) escreve o registro r na posio apontada por WL e incrementa WL de um. Os procedimentos extractup e extractlow removem e retornam, respectivamente, o maior e o menor elemento do buffer interno. Alm disso, ambos decrementam no_buffer de um.
procedure particao (esq, dir, i, j) RU := WU := dir; {Apontadores superiores de E/S} RL := WL := esq; {Apontadores inferiores de E/S} no_buffer := 0; {Nmero de registros no buffer} Linf := ; {Limite inferior de partio} Lsup := + ; {Limite superior de partio} up_reading; {flag que faz com que a leitura seja alternada} last_read; {contm o ltimo registro lido} i := esq 1; {inicia com o subarquivo esquerdo vazio} j := dir + 1; {inicia com o subarquivo direito vazio} while RU RL do if no_buffer < K - 1 then if up_reading then readup() else readlow(); end if inserir_buffer(); {insere last_read no buffer e incrementa no_buffer} else if RU = WU then readup(); else if RL = WL then readlow(); else if up_reading then readup() else readlow(); end if end if end if if last_read.chave > Lsup then j := WU; writeup(last_read); else if last_read.chave < Linf then i := WL; writelow(last_read); else inserir_buffer(); if WL esq < dir - WU then r := extractlow(); writelow(r); else r := extractup(); writeup(r); end if end if

end if end if end do while WL WU do r := extractlow(); writelow(r); end do end procedure Cdigo 2: procedimento que realiza a partio do arquivo a ser ordenado.

Como os controladores de disco lem e escrevem os dados em blocos, Monard [Monard, 80] tambm props a utilizao de buffers para leitura e escrita de registros, com o objetivo de diminuir o nmero de operaes de E/S. Isto pode ser feito utilizando dois buffers de entrada e dois de sada. Desta forma, cada registro pode ser lido do buffer de entrada do extremo esquerdo ou direito do arquivo e escrito no buffer de sada do extremo esquerdo ou direito. Quando um buffer de leitura de um dos extremos estiver vazio e uma leitura for solicitada ao mesmo, o buffer reabastecido pela leitura de um novo bloco de dados daquele extremo no arquivo original. Uma analogia pode ser feita em relao aos buffers de sada, pois quando um destes estiver cheio e uma escrita for solicitada, o buffer deve ser descarregado no respectivo extremo do arquivo original. Isto deve ser feito antes do novo registro ser armazenado no buffer. O Quicksort Externo, tal como descrito, foi implementado com o objetivo de verificar a sua eficincia de tempo e espao em relao aos programas Nitrosort [Nitrosort, 03] e Sort. Monard [Monard, 80] no especificou a forma de gerncia do buffer interno de tamanho K. Apenas sugeriu algumas estruturas, como arranjo ordenado, heaps paralelos e outros. Neste trabalho, a estrutura escolhida para o buffer foi uma lista duplamente encadeada implementada em vetor e mantida ordenada, de forma que o maior e o menor registros possam ser removidos do buffer com custo O(1). Esta abordagem impe a sobrecarga de manter a lista ordenada. Porm, testes executados indicaram que tal sobrecarga no compromete o desempenho do Quicksort Externo, desde que o buffer no seja muito grande. Aps termos detalhado todas as caractersticas do Quicksort Externo, exibiremos agora a sua complexidade, a qual foi demonstrada em Monard [Monard, 80]. A n complexidade de melhor caso do algoritmo O ( III ) , que ocorre, por exemplo, b quando o arquivo de entrada j se encontra ordenado. A complexidade de pior caso n2 O ( IV ) e ocorre quando um dos arquivos retornados pela rotina de partio tem o K maior tamanho possvel e o outro vazio, ou seja, a rvore gerada pelas chamadas recursivas totalmente degenerada. Monard [Monard, 80] provou que, medida que n cresce, tanto a probabilidade de ocorrncia do pior caso quanto a do melhor tendem a zero, sendo que a probabilidade do melhor caso sempre maior do que a do pior. Enfim, em uma demonstrao exaustiva, Monard [Monard, 80] provou que a n n complexidade do caso mdio O log (V ) . Comparando esta complexidade b K com a equao (I), apresentada na seo 1, percebe-se que na mdia o Quicksort Externo executa um nmero pouco maior de operaes de E/S do que o exigido no limite inferior do problema de ordenao externa.

3. Estudos empricos
Os estudos empricos foram realizados no ambiente Cygwin [Cygwin, 03] em uma mquina equipada com um processador AMD Atlon XP 2GHz, 512 MB de memria RAM e com o sistema operacional Windows XP. Os arquivos utilizados nos testes continham registros de inteiros de 4 bytes gerados aleatoriamente. Os tamanhos destes arquivos variaram de 1 MB a 1536 MB, como pode ser visto nas Tabelas 1 e 2. Para possibilitar uma comparao justa, procurou-se por softwares eficientes que realizassem ordenao in situ, tal como o Quicksort Externo. No entanto, como no se teve acesso a nenhum software com tais caractersticas, foi utilizado nos testes um programa que no ordena arquivos de forma in situ, mas que comprovadamente eficiente. O programa escolhido foi o Nitrosort, desenvolvido pela Cole-Research [Nitrosort, 03]. O Nitrosort necessita de, no mnimo, o dobro do espao do arquivo original na memria externa e, portanto, no pode ser classificado como um software de ordenao in situ. Por ser um software proprietrio, no tivemos acesso ao mtodo de ordenao externa utilizado pelo Nitrosort. No entanto, ao entrar em contato com os desenvolvedores do mesmo, estes nos informaram que o mtodo baseado na ordenao interna e intercalao externa de runs. Um run um segmento do arquivo original que ordenado na memria interna. Existem vrios mtodos na literatura baseados neste paradigma, tais como os citados em Islam [Islam, 03] e Leu [Leu, 00], sendo que o ltimo apresenta um algoritmo timo. Em seguida, tratou-se de delimitar a quantidade de memria interna que seria utilizada pelos algoritmos avaliados. Foram executados testes preliminares, nos quais o Quicksort Externo apresentou um bom desempenho para buffers capazes de armazenar 100 registros. Como foram utilizados cinco buffers, a memria total consumida pelo Quicksort Externo foi de 2000 bytes. O Nitrosort permite variar a quantidade de memria interna utilizada, sendo que o valor mnimo suportado de 1 MB. Para fazer uma comparao justa, procurou-se encontrar a menor quantidade de memria com a qual o Nitrosort apresentasse um bom desempenho. Esta quantidade foi especificada em 3 MB, j que para valores inferiores, o Nitrosort demonstrou ser muito menos eficiente que o Quicksort Externo. O valor ideal, sugerido pelos desenvolvedores do software, de 21 MB. Neste caso, o Nitrosort chegou a ser duas vezes mais rpido que o Quicksort Externo. Porm, medida que o arquivo cresce, esta proporo diminui rapidamente e, aps um determinado limite, o Quicksort Externo mais rpido. Esta caracterstica tambm pode ser observada nos dados obtidos com 3 MB, veja Tabela 1 e Grfico 1. Os dados coletados nos testes foram coerentes com a complexidade de caso mdio para o Quicksort Externo exibida na seo 2. Para averiguar isto, pode-se utilizar a seguinte equao para estimar o tempo de execuo a partir da complexidade de caso n n mdio: Texe = log t (VI ) , onde t uma constante que foi obtida a partir da mdia b K de sub-constantes calculadas pela aplicao da equao (VI), utilizando os tempos de execuo da coluna Q. E. (Quicksort Externo) da Tabela 1. O ideal seria que o valor de t fosse dado pela equao t = Cte t1 op E / S , onde Cte seria uma constante assinttica e t1
op E/S o tempo de execuo de uma operao de E/S na arquitetura onde os testes foram efetuados.

Tabela 1. Tempos de execuo em segundos Tamanho do Arquivo (MB) 1 2 4 8 16 32 64 128 256 512 1024 1536 Estimado 1.07 2.31 4.98 10.68 22.79 48.45 102.64 216.76 456.50 958.94 2009.77 3095.29 Quicksort Externo 1.19 2.23 4.92 11.14 20.05 49.42 85.73 184.61 412.48 1029.41 2139.80 3890.72 Nitrosoft 1.44 1.56 2.33 3.61 7.19 13.59 26.92 56.33 123.30 560.45 2154.42 4650.08

Grfico 1: Grfico dos dados da Tabela 1

Como mencionado na seo 1, o Quicksort Externo foi comparado com o software Sort. Assim como o Nitrosort, Sort no efetua ordenao in situ, pois tambm necessita de memria externa extra para ordenar o arquivo de entrada. Uma peculiaridade do Sort que ele somente ordena linhas de um arquivo texto. Por isso, os testes com o Sort foram executados separadamente e os dados de entrada, tanto do Quicksort Externo quanto do Sort, tiveram que ser adaptados de forma que os arquivos possussem o mesmo tamanho e o mesmo nmero de registros. Um registro do arquivo de entrada para o Quicksort Externo corresponde a uma linha do arquivo de entrada para o Sort. Os dados coletados nos testes so exibidos na Tabela 2 e ilustrados no Grfico 2.
Tabela 2. Tempos de execuo em segundos Tamanho do Arquivo (MB) 1 2 Quicksort Externo 1.17 1.84 Sort 0.38 1.08

4 8 16 32 64 128 256 512 1024

4.98 10.00 19.58 41.45 98.83 161.38 425.33 1047.64 2077.05

2.19 4.69 9.89 20.50 42.11 84.41 304.38 980.34 2137.23

Grfico 2: Grfico dos dados da Tabela 2

Avaliando os resultados apresentados em termos das mtricas propostas na seo 1, percebe-se que a eficincia de tempo do Quicksort Externo est prxima tanto do Nitrosort quanto do Sort. Sendo que, com o aumento do tamanho da entrada, o Quicksort Externo tende a ser mais eficiente. Em contrapartida, em termos de espao de memria interna utilizada, o Quicksort Externo cerca de 1500 vezes mais eficiente que o Nitrosort. Este valor foi obtido pela razo da memria interna delimitada para o Nitrosort (3 MB) e a delimitada para o Quicksort Externo (2000 B). No foi possvel fazer a mesma anlise para o Sort, pois no foi encontrado o tamanho da memria interna que este utiliza como buffer para operaes de E/S. Enfim, foram executados dois testes comparando o Quicksort tradicional em ambiente de memria virtual e o Quicksort Externo. Novamente, o Quicksort Externo se mostrou mais eficiente com o crescimento do tamanho da entrada, veja Tabela 3.
Tabela 3. Tempos de execuo em segundos Tamanho do Arquivo (MB) 1024 1536 Quicksort Externo 2139.80 3890.72 Quicksort em memria virutal 2080.59 5191.81

4. Concluses
Diante do que foi apresentado, pode-se concluir que o Quicksort Externo um algoritmo muito adequado para ambientes com poucos recursos. Isto porque ele faz ordenao in situ de forma eficiente, mesmo com pouca memria interna disponvel. Alm disso, seu comportamento, no que diz respeito a tempo de execuo, est prximo do comportamento verificado para os softwares utilizados nas comparaes. Tal comportamento era esperado, pois o Quicksort Externo, apesar de possuir uma complexidade de pior caso quadrtica, possui uma complexidade de caso mdio prxima do nmero mnimo de operaes de E/S necessrias para ordenar externamente um arquivo. Como proposta para futuros trabalhos, pode-se sugerir, primeiramente, um estudo do impacto no tempo de execuo do Quicksort Externo de diferentes estruturas de dados para gerenciamento do buffer interno de tamanho K. Alm disso, este mesmo estudo poderia determinar o tamanho ideal do buffer interno e dos buffers de entrada e sada para cada uma das estruturas. Outro estudo poderia ser feito no sentido de tentar melhorar o Quicksort Externo, visando diminuio do nmero de operaes de E/S realizadas. importante mencionar que o problema de ordenao externa tem sido muito pesquisado e novas tcnicas e algoritmos foram propostos aps a publicao do Quicksort Externo. Assim, um estudo poderia buscar a conciliao das vantagens dessas novas tcnicas com as apresentadas para o Quicksort Externo em um novo algoritmo.

5. Referncias Bibliogrficas
[Cygwin, 03] [Hoare, 62] [Islam, 03] Cygwin. A Linux-like environment for Windows. Disponvel em <http://www.cygwin.com>, acessado em agosto de 2003. Hoare, C.A.R. Quicksort. The Computer Journal 5, p. 1015, 1962. Islam, R., Adnan, N., Islam, N., Hossen, S. A new external sorting algorithm with no additional disk space. Information Processing Letters 86, p. 229233, 2003. Leu, F.C., Tsai, Y.T., Yang, C.Y. An efficient external sorting algorithm. Information Processing Letters 75, p. 159163, 2000. Monard, M.C. Projeto e Anlise de Algoritmos de Classificao Externa Baseados na Extratgia de Quicksort. D. Tese, Pontifcia Univ. Catlica, Rio de Janeiro, 1980. Nitrosort. Software de ordenao externa desenvolvido pela ColeResearch. Disponvel em <http://www.cole-research.com>, acessado em agosto de 2003. Verkamo, A.I. Performance of Quicksort Adapted for Virtual Memory Use. The Computer Journal, v. 30, n. 4, 1987. Ziviani, N. Projeto de Algoritmos com Implementaes em Pascal e C. ed. Pioneira Thomson Learning, 1993.

[Leu, 00] [Monard, 80]

[Nitrosort, 03]

[Sedgewick, 83] Sedgewick, R. Algorithms. Addison-Wesley, Reading, Mass., 1983. [Verkamo, 87] [Ziviani, 93]

You might also like