You are on page 1of 7

Algoritmos de Ordenao

Carlos Torro
55381

Joo Martins
55385

Maria Couceiro
53964

Resumo:

Neste artigo so apresentados vrios algoritmos de ordenao: bubble sort, mergesort, quicksort, hyperquicksort, rank sort, counting sort e radix sort. feita uma descrio do seu funcionamento em srie e em paralelo, fazendo-se referncia a vantagens e desvantagens e problemas resultantes do seu uso. Conclumos que, na grande maioria dos casos, a implementao paralela dos algoritmos produz melhores resultados a nvel de complexidade temporal que em srie.

1 Introduo
A ordenao um dos aspectos fundamentais das cincias computacionais. Torna-se, ento, importante reduzir ao mximo a complexidade temporal dos algoritmos que lidam com este problema. As melhores ordenaes em srie normalmente demoram O(n log n), tempo que tende a agravar com o aumento do nmero de elementos. Deste modo, foram desenvolvidas verses para funcionamento em paralelo destes algoritmos, cujo objectivo diminuir consideravelmente o tempo de execuo dos mesmos. Neste texto vamos abordar vrios algoritmos de ordenao. Relativamente aos que realizam operaes de comparao e troca, descrevemos o bubble sort, quicksort e hyperquicksort, mergesort, odd-even mergesort e bitonic mergesort. Tambm falamos sobre o rank sort e o counting sort, que no recorrem a este tipo de operaes. No que diz respeito a algoritmos que obtm uma performance muito superior quando paralelizados, vamos descrever o radix sort.

x2, onde na posio x2 ficar o maior dos nmeros que se encontra nas posies x1 e x2. Este processo repetido de forma anloga at chegar comparao entre as posies xn-1 e xn. Este processo anterior de comparaes e trocas ser considerado uma fase do algoritmo, sendo o algoritmo bubble sort constitudo (na pior das hipteses) por n-1 fases semelhantes anterior.

2.2 Paralelo
Aps esta breve descrio do algoritmo sequencial, a questo que se impe a seguinte: ser que possvel uma verso paralela eficiente deste algoritmo? A resposta a esta pergunta afirmativa. Atravs da tcnica de pipelining possvel melhorar o desempenho do algoritmo, em comparao com a verso sequencial. Isto deve-se ao facto de ser possvel serem executadas vrias fases em simultneo na verso com pipelining. possvel tal mtodo, pois como cada fase s faz uma comparao por cada par de posies, quando a primeira fase se encontra na comparao entre as posies x2 e x3, a segunda fase j pode (sem problema algum) fazer a comparao entre as posies x0 e x1. A terceira fase, ter incio quando a segunda fase estiver a comparar as posies x2 e x3, e a primeira fase, por sua vez, se encontrar na comparao das posies x4 e x5. (Ver Figura 1) Existe ainda uma variao do algoritmo bubble sort, cujo nome odd-even (transposition) sort, que consiste em duas fases, a fase even (par) e a fase odd (mpar). Na fase even (par), comparam-se (e se necessrio trocam-se) as posies pares com a posio seguinte a cada uma delas. Na fase odd (mpar), a ideia anloga anterior, mas para as posies mpares. (Ver Figura 2)

2 Bubble Sort
2.1 Sequencial
O algoritmo de ordenao bubble sort usa uma estratgia de comparao e troca, que aplicada em vrias iteraes sobre os dados a ser ordenados. Passo a explicar os passos do algoritmo sequencial. Partindo do principio que se deseja ordenar (de forma crescente) um vector de nmeros nas seguintes posies: x0, x1, , xn-1, xn. O algoritmo comea por comparar o nmero que se encontra na posio x0 com o da posio x1, e troca (quando necessrio) os nmeros de maneira a ficar o maior dos dois na posio x1. De seguida, repete o mesmo procedimento para as posies x1 e

Figura 1 Bubble sort com pipelining

Figura 2 Odd-Even transposition sort em paralelo Como de prever, esta soluo em sequencial no traz benefcios nenhuns em relao ao bubble sort (sequencial), mas o mesmo j no se pode afirmar da verso paralela desta, que bastante mais eficiente. Esta soluo paralela tem complexidade O(n), enquanto que o algoritmo bubble sort na sua verso sequencial, apresenta uma complexidade de O(n2). Inicialmente, durante todo o processo da diviso da lista, no feita qualquer computao sobre os elementos e sua ordem na lista, e a primeira lista de quatro elementos apenas separada em metade, ficando duas listas, sendo de seguida o mtodo repetido, ficando desta vez todos os elementos separados. na fase da juno (merge) que o algoritmo ordena todos os elementos da forma pretendida. Neste caso, em que queremos ordenar de forma crescente, o algoritmo pega nos primeiros dois elementos e junta-os numa lista, ficando o menor valor na primeira posio e o maior na segunda posio. Para os dois ltimos elementos que sobram, utiliza o mesmo mtodo. Este processo agora repetido para as duas listas criadas anteriormente, juntando os elementos de cada uma dessas duas listas numa nica lista, ficando essa lista ordenada de forma crescente.

3 Merge Sort
3.1 Sequencial
O algoritmo merge sort consiste em ir separando em metades uma lista de elementos, at ficar com todos os elementos separados. Esta tcnica tem o objectivo de dividir-para-conquistar. Aps estes elementos estarem separados, o algoritmo procede sua juno (merge), retornando no final uma nica lista com todos os elementos ordenados. Vamos considerar a ttulo de exemplo, uma lista de quatro elementos sem ordem alguma, e que se querer ordenar de forma crescente todos os seus elementos.

3.2 Paralelo
A verso simples paralela, baseia-se em atribuir a cada processador uma lista de

Figura 3 Merge sort sequencial

A lista final ordenada, E, constitudas pelos elementos: e1, e2, ..., e2n, obtida atravs das seguintes regras (1 i n-1): e2i = min{ ci+1, di } e2i+1 = max{ ci+1, di } Basicamente, esta lista E obtida pela comparao das posies pares e mpares das listas C e D. O primeiro elemento da lista E, e1, dado por c1, e o mesmo acontece com o ultimo elemento, e2n, que dado por dn. Isto deve-se ao facto, de em c1 estar o elemento menor das listas C e D, e de em dn estar o maior elemento das listas C e D.

3.4 Anlise das verses


O merge sort sequencial tem uma complexidade temporal O(n.logn). O que bastante bom para um algoritmo de ordenao sequencial. O odd-even merge sort em comparao com a verso sequencial bastante superior, pois apresenta uma complexidade temporal O(log2n) com n processadores.

elementos, na parte inicial da diviso da lista a ordenar. Esta verso tem o problema de em algumas fases do algoritmo ser necessria bastante comunicao entre processadores. Mas por outro lado, esta verso torna-se bastante leve a nvel computacional para cada um dos processadores envolvidos, pois cada processador responsvel por uma lista pequena.

4 Quicksort
O algoritmo Quicksort, inventado por C.A.R. Hoare, um algoritmo recursivo que tem como base a comparao de valores para ordenar uma lista desordenada. Mais especificamente, quando passada uma lista de nmeros, o algoritmo selecciona um nmero dessa lista, tornando-o pivot. Aps isso, a lista partida em duas sublistas: uma contendo nmeros inferiores ao pivot, e outra com os nmeros superiores. Chama-se depois a si mesma recursivamente para ordenar as duas sublistas. A funo retorna a concatenao da primeira lista, pivot e segunda lista.

3.3 Odd-Even merge sort


Este algoritmo tem como objectivo ordenar duas listas ordenadas, numa s lista ordenada. Isto apresenta potencial, para ser invocado de maneira recursiva. Na parte de juno das listas no algoritmo merge sort. Considerando a lista A = a1, a2, ..., an e a lista B = b1, b2, ..., bn. O algoritmo comea por criar uma lista C, constituda pelas posies (ndices) mpares de ambas as listas, ou seja, C = a1, a3, ..., an-1, b1, b3, ..., bn-1. Existe o processo anlogo para as posies (ndices) pares, sendo criado a lista D = a2, a4, ..., an, b2, b4, ..., bn. Para maior facilidade de percepo futura, os elementos da lista C estaro referenciados da seguinte forma: c1, c2, ..., cn, e o mesmo para os elementos da lista D.

4.1 Quicksort Paralelo


Existem algumas vantagens na utilizao deste algoritmo, no que toca a paralelizao de algoritmos. Primeiro, porque considerado dos algoritmos mais rpidos no que trata a ordenao atravs de comparao de valores. Em segundo lugar, porque como um algoritmo que se chama a si prprio recursivamente, tem concorrncia natural, sendo que essas chamadas podem executar-se independentemente.

Em relao ao desenvolvimento deste algoritmo, inicialmente os valores encontram-se distribudos ao longo dos processos. Escolhemos ento um pivot de cada um dos processos e divulgamo-lo. Aps isso, cada processo divide os seus nmeros em duas listas: aqueles que so menores ou iguais ao pivot, e aqueles que so maiores do que o pivot (que chamaremos aqui de lista menor e lista maior respectivamente). Cada processo na parte de cima da lista de processos envia a sua lista menor para um processo concorrente na parte inferior da lista de processos e recebe uma lista maior em retorno. Neste momento, os processos na parte superior da lista de processos tm valores maiores do que o pivot, e os processos na parte inferior da lista de processos tm valores menores ou iguais ao pivot. A partir daqui os processos dividem-se em dois grupos e o algoritmo chamado de novo. Em cada grupo de processos distribudo um pivot. Os processos dividem a sua lista e trocam valores com processos concorrentes. Aps log p recurses, cada processo tem uma lista desordenada de valores, que so diferentes dos valores possudos pelos outros processos. Cada processo pode agora ordenar a lista que controla usando quicksort sequencial. Em relao complexidade, se tivermos p processadores, podemos dividir a lista de n elementos em p sub-listas em O(n). Aps isso, a sua ordenao ser em O((n/p)log(n/p)). Uma das vantagens deste algoritmo em relao a outros algoritmos em paralelo o facto de no ser necessria a sua sincronizao. Um processo criado por cada sub-lista gerada, sendo que esse processo s trabalha com essa lista, no comunicando com os outros processos. O tempo de execuo do algoritmo comea quando o primeiro processo comea a sua execuo, e termina quando o ultimo processo termina a sua execuo. por isto que importante assegurar que todos os processos tenham a mesma carga de trabalho, para que terminem todos por volta do mesmo tempo. Neste algoritmo, a carga de trabalho relacionada com o nmero de elementos controlados pelos processos. Este algoritmo tem como ponto negativo que neste caso faz um mau trabalho a balancear o tamanho das listas. Tem que se conseguir um pivot perto da mediana

dos valores, para garantir maior diviso de trabalho pelos processos. No entanto, poderia ser feito um melhor balanceamento do tamanho da lista pelos processos, se em vez de escolher um nmero arbitrrio da lista para ser pivot, escolhssemos um valor mais perto do valor mediano da lista ordenada. Este ponto a motivao por trs do prximo algoritmo em paralelo: hyperquicksort.

4.2 Hyperquicksort
Este algoritmo, inventado por Wagar, comea onde o quicksort acaba. Considerando que os valores continuam a mover-se de processos para outros processos, teremos ento um pivot para dividir os nmeros em dois grupos: a parte superior e a parte inferior. Devido lista de elementos de cada processo estar ordenada, o processo responsvel por fornecer o pivot pode usar o mediano da sua lista como pivot. Este pivot ento, mais prximo do verdadeiro mediano da inteira lista desordenada do que escolhendo um valor arbitrrio. Os prximos trs passos do hyperquicksort so os mesmos do que o quicksort paralelo. Aps a execuo desses passos, cada processo tem uma sub-lista ordenada prpria e uma sub-lista ordenada que recebe de um outro processo. Esse processo vai ento juntar as duas listas, para que todos os elementos que controla estejam ordenados. importante que os processos terminem esta fase com listas ordenadas, porque quando o algoritmo se chamar de novo, dois processos precisaro de escolher o elemento mediano das suas listas como pivot. O hyperquicksort assume que o nmero de processos um expoente de 2. Se imaginarmos a lista de processos como um hypercube, poderemos modelar as comunicaes, de modo a que estas sejam sempre feitas entre pares de processos adjacentes.

Figura 4: Neste exemplo h 8 processos, fazendo log p = 3 vezes separar-e-juntar

H a referir tambm a eficincia deste algoritmo, onde para p processadores, sero ordenados n elementos, onde n >> p. No incio do algoritmo, cada processo no tem mais do que n/p valores. A esperada complexidade temporal do passo inicial do quicksort [(n/p)log(n/p)]. Assumindo que cada processo guarda n/2p valores e transmite n/2p valores em cada passo de separar-e-juntar, o numero esperado de comparaes necessrias para juntar as duas listas numa nica lista ordenada n/p. O numero de comparaes feitas durante o algoritmo todo [(n/p) (logn+logp)], para log p iteraes. Assumindo que cada processo passa metade dos seus valores em cada iterao, o tempo necessrio para enviar e receber n/2p valores ordenados para e de outro processo, (n/p). A complexidade do tempo sequencial do quicksort n.log n. O overhead da comunicao do hyperquicksort p vezes a complexidade da comunicao, ou (n.logp). Para finalizar, o hyperquicksort tem duas desvantagens que limitam as suas vantagens. Primeiro, o nmero esperado de vezes que um valor passada de um processo para outro (logp)/2. Este overhead da comunicao limita a escalabilidade do algoritmo em paralelo. Poderamos reduzir este overhead se consegussemos encontrar uma maneira de enviar as chaves directamente para os seus destinos finais. Em segundo lugar, a maneira como os pivots so escolhidos podem levar a certos problemas no balanceamento da carga de trabalho entre processos. Se consegussemos ter exemplares de todos os processos, poderamos ter uma melhor diviso das listas de elementos pelos processos.

um vector com n nmeros, a[0] a[n-1], a[0] comea por ser comparado a todos os outros elementos, sendo a soma total dos menores que ele guardados em rank. Este valor o seu ndice no vector ordenado b, onde colocado. A mesma operao repetida para todos os elementos do vector a. Segue-se uma possvel implementao para este algoritmo, tendo em conta a existncia de valores duplicados:
for(i=0; i < n; i++){ rank = 0; for(j=0; j < n; j++){ if(a[i] < a[j] || (a[i] == a[j] && j < i)) rank++; b[rank] = a[i]; }

5 Rank Sort
O rank sort, tambm conhecido como enumeration sort, um exemplo de um algoritmo de ordenao estvel, isto , os registos aparecem na sequncia ordenada pela mesma ordem que esto na sequncia original, mantendo assim a sua posio relativa. O seu modo de funcionamento consiste em determinar a quantidade de nmeros menores que um determinado nmero, sendo assim calculada a sua posio (rank) na lista ordenada. Tomando como exemplo

A nvel de complexidade, este algoritmo pouco eficiente quando executado em modo sequencial, uma vez que faz n-1 comparaes n vezes, ficando o algoritmo com n(n-1) iteraes, o que resulta numa complexidade temporal de O(n2). Como necessrio existir um acesso partilhado ao vector, este algoritmo mais indicado para sistemas de memria partilhada. O clculo da posio final de cada nmero no vector ordenado dividido por n processadores, que a determinam em paralelo, ficando assim o algoritmo com uma complexidade temporal de O(n). No entanto, possvel implement-lo em sistemas de memria distribuda. Neste caso, um processo central (master) distribui pelos outros processadores (slaves) n/p elementos do vector, sendo p o nmero total de processadores. Cada processador fica responsvel por calcular o rank de cada um dos seus n/p elementos. No final, os clculos so reportados ao processo central, que constri o vector ordenado. Esta distribuio s compensa quando n suficientemente grande, devido ao custo das operaes de comunicao. Uma outra limitao do uso deste algoritmo neste tipo de sistemas prende-se com a utilizao de uma grande quantidade de memria, uma vez que cada processador precisa de uma cpia do vector desordenado e de um vector do tamanho deste ltimo para poder posicionar os elementos repetidos ordenados na posio correspondente. Utilizando n2 processadores e uma estrutura em rvore, a complexidade temporal diminui para O(log n). Cada processador executa a comparao de um elemento com outro, somando-se os

resultados de cada comparao cada vez que se muda de nvel na rvore, como se pode ver na figura 5.

c[i] = 0; for(i = 1; i <= m; i++) c[a[i]]++; for(i = 2; i <= m; i++) c[i] = c[i] + c[i-1]; for(i = 1; i <= n; i++){ b[c[a[i]]] = a[i]; c[a[i]]--; }

Figura 5: Computao do clculo do rank em paralelo. Como a utilizao de n2 processadores (e at mesmo de n processadores, quando n muito grande) se torna proibitiva, comum agrupar nmeros e distribu-los pelos processadores disponveis. Partindo do princpio que temos m grupos, seriam apenas necessrios n/m processadores para calcular a posio no vector ordenado em cada grupo de nmeros (sem que este clculo seja paralelizado). No entanto, o nmero de operaes em cada processador aumentaria m vezes.

Este cdigo tem complexidade temporal de O(n + m), mas caso m = O(n), O algoritmo corre em O(n). Na paralelizao do counting sort, usa-se a verso paralela do prefix sum, que requer um tempo de O(log n) para n-1 processadores. Para atingir este tempo, partimos recursivamente o vector c ao meio e somamos as duas metades tambm recursivamente, estando associada a esta computao uma rvore binria completa, em que cada n interno contm a soma das suas folhas descendentes. A ordenao final pode ser feita em O(n/p), caso tenhamos n < p processadores, dividindo-se o vector em p sub-vectores, cada um com n/p elementos, ou ento O(1), caso tenhamos n processadores, em que cada um executa o corpo do ciclo.

7 Radix Sort
O radix sort um dos algoritmos de ordenao mais utilizados, devido sua rapidez e simplicidade de implementao. Parte do pressuposto que os dgitos representam valores e que a sua posio, que est ordenada do menos significativo para o mais significativo, indica o seu peso relativo. Imaginando que um nmero tem b bits (ou dgitos, caso se esteja a falar de notao decimal), na sua verso mais simples, o algoritmo ordena os nmeros em b passagens, sendo que em cada n-sima passagem se ordena pelo n-simo bit menos significativo. Este nmero de passagens pode ser reduzido de b para b/r se se considerar blocos de r dgitos em vez de um nico bit. A complexidade temporal vai depender do algoritmo de ordenao usado, que tem de ser estvel, de modo a preservar a ordem relativa dos elementos. O counting sort um algoritmo de ordenao muito usado pelo radix sort, cuja complexidade temporal em modo sequencial O(n + m), sendo que n corresponde ao nmero de elementos inteiros, estando cada um deles entre, por exemplo, 1 e m. Com nmeros de dimenso r, ficamos com um intervalo de 1 a 2r-1 e b/r fases do algoritmo. Assim,

6 Counting Sort
Outro exemplo de um algoritmo estvel o counting sort. Sendo uma optimizao do rank sort para o caso em que todos os nmeros a ordenar so inteiros, reduz a complexidade temporal da execuo em srie de O(n2) para O(n). Tal como no rank sort, a ideia fundamental determinar, para cada nmero i, a quantidade de elementos menores que ele. Os vectores a e b, ambos com dimenso n, contm, respectivamente, os nmeros desordenados e ordenados. Existe tambm um vector c, de dimenso m, que contm um elemento para cada valor possvel de a, por exemplo, de 1 at m. Para calcular a quantidade de elementos inferior a um dado nmero, utiliza-se o mtodo denominado prefix sum, que consiste na soma parcial de todas as posies de um dado vector. Segue-se uma possvel implementao para este algoritmo, tendo em conta a existncia de valores duplicados:
for(i = 1; i <= m; i++)

obtm-se uma complexidade temporal em modo sequencial de O( b/r ( n + 2r )), mas se b e r forem constantes, a complexidade baixa para O(n). Podemos paralelizar o radix sort usando um algoritmo de ordenao paralelo, como o counting sort descrito na seco anterior, atingindo-se assim um tempo de O(log n) com n processadores e b e r constantes. No entanto, em sistemas de memria distribuda, para grandes quantidades de dados, o tempo gasto em comunicao demasiado elevado e o balanceamento da carga muito irregular, pois no se sabe partida o formato de todos os elementos a ordenar. Consequentemente, foram propostas vrias formas de dividir a carga entre os vrios processadores, com o objectivo de diminuir estes problemas. Uma dessas propostas denominada de Load Balanced Parallel Radix Sort e consiste em atribuir a cada processador exactamente o mesmo nmero de elementos a ordenar, eliminando assim o problema da distribuio de carga, mas gastando ainda muito tempo a redistribuir os elementos pelos processadores. O Partitioned Parallel Radix Sort veio solucionar o problema de comunicao desta proposta, uma vez que elimina a redistribuio global de elementos, ao orden-los, inicialmente, pelos seus g bits mais significativos e, depois, distribuir grupos destes elementos pelos processadores disponveis, onde so ordenados pelos seus b g bits menos significativos, reduzindo assim a troca de mensagens entre processadores.

9 Referncias
1. Michael Quinn, Parallel Programming, McGrawHill, 2003 2. Barry Wilkinson and Michael Allen, Parallel Programming: Techniques and Applications Using Networked Workstations and Parallel Computers, Prentice Hall, 2005 3. Philippas Tsigas and Yi Zhang, A Simple, Fast Parallel Implementation of Quicksort and its Performance Evaluation on SUN Enterprise 10000 4. N. M. Amato, R. Iyer, S. Sundaresan, Y. Wu, A Comparison of Parallel Sorting Algorithms on Different Architectures, 1998 5. S. Lee, M. Jeon, D. Kim, A. Sohn, Partitioned Parallel Radix Sort, 2002 6. A. Sohn, Y. Kodama, Load Balanced Parallel Radix Sort, 1998 7. http://beowulf.csail.mit.edu/18.337/book/Lec ture_03-Parallel_Prefix.pdf, 2006

8 Concluso
Durante a elaborao deste artigo, pudemos concluir que a execuo em paralelo dos algoritmos estudados aumenta consideravelmente a eficincia temporal da ordenao de elementos. H que referir que existem outros que no foram aqui abordados, pois no os considermos to relevantes quanto os aqui expostos. Foi ainda possvel observar que, relativamente investigao nesta rea, h uma grande preocupao em optimizar certos aspectos dos algoritmos existentes de modo a reduzir os overheads introduzidos pela comunicao e distribuio de carga pouco equilibrada, que continuam a limitar o seu funcionamento.

You might also like