Articulo de referencia

Ordenación de muestras

Samplesort es un algoritmo de ordenación de divide y vencerás que se utiliza frecuentemente en sistemas de procesamiento paralelo. [ 1 ] Los algoritmos convencionales de ordenac...

Samplesort es un algoritmo de ordenación de divide y vencerás que se utiliza frecuentemente en sistemas de procesamiento paralelo. [ 1 ] Los algoritmos convencionales de ordenación de divide y vencerás dividen el array en subintervalos o cubetas. Estas cubetas se ordenan individualmente y luego se concatenan. Sin embargo, si el array no está distribuido uniformemente, el rendimiento de estos algoritmos de ordenación puede verse significativamente afectado. Samplesort resuelve este problema seleccionando una muestra de tamaño s de la secuencia de n elementos y determinando el rango de las cubetas ordenando la muestra y eligiendo p −1 < s elementos del resultado. Estos elementos (llamados divisores) dividen el array en p cubetas de tamaño aproximadamente igual. [ 2 ] Samplesort se describe en el artículo de 1970, "Samplesort: A Sampling Approach to Minimal Storage Tree Sorting", de WD Frazer y AC McKellar. [ 3 ]

Algoritmo

Samplesort es una generalización de Quicksort . Mientras que Quicksort divide su entrada en dos partes en cada paso, basándose en un único valor llamado pivote, Samplesort toma una muestra más grande de su entrada y divide sus datos en grupos según corresponda. Al igual que Quicksort, luego ordena recursivamente los grupos.

Para diseñar una implementación de ordenación por muestras, es necesario decidir el número de cubetas p . Una vez hecho esto, el algoritmo real opera en tres fases: [ 4 ]

  1. Muestre p −1 elementos de la entrada (los divisores ). Ordénelos; cada par de divisores adyacentes define un cubo .
  2. Recorre los datos en un bucle, colocando cada elemento en el contenedor correspondiente. (Esto puede significar: enviarlo a un procesador, en un sistema multiprocesador ).
  3. Clasifica cada uno de los cubos.

El resultado final ordenado es la concatenación de los cubos.

Una estrategia común consiste en establecer p igual al número de procesadores disponibles. Los datos se distribuyen entre los procesadores, que realizan la clasificación de los grupos utilizando algún otro algoritmo de clasificación secuencial.

Pseudocódigo

El siguiente listado muestra el algoritmo de tres pasos mencionado anteriormente como pseudocódigo y muestra cómo funciona el algoritmo en principio. [ 5 ] A continuación, A son los datos sin ordenar, k es el factor de sobremuestreo, que se analizará más adelante, y p es el número de divisores.

función sampleSort(A[1..n], k , p ) // Si el tamaño promedio del cubo está por debajo de un umbral, cambia a, por ejemplo, ordenación rápida Si n / k < umbral , entonces smallSort(A) /* Paso 1 */ seleccionar S = [ S 1 , ..., S ( p −1) k ] aleatoriamente de // seleccionar muestras ordenar S // ordenar muestra [ s 0 , s 1 , ..., s p −1 , s p ] <- [-∞, S k , S 2 k , ..., S ( p −1) k , ∞] // seleccionar divisores /* Paso 2 */ Para cada a en A, encuentra j tal que s j −1 < a <= s j coloca a en el cubo b j /* Paso 3 y concatenación */ return concatenar(sampleSort( b 1 ), ..., sampleSort( b k ))

El pseudocódigo difiere del algoritmo original de Frazer y McKellar. [ 3 ] En el pseudocódigo, se llama a samplesort de forma recursiva. Frazer y McKellar llamaron a samplesort solo una vez y utilizaron quicksort en todas las iteraciones siguientes.

Complejidad

La complejidad, dada en notación Big O , para una implementación paralela conpag{\displaystyle p}procesadores:

Encuentra los divisores.

O(nortepag+registro(pag)){\displaystyle O\left({\frac {n}{p}}+\log(p)\right)}

Enviar a los contenedores.

O(pag){\displaystyle O(p)}para leer todos los nodos
O(registro(pag)){\displaystyle O(\log(p))}para radiodifusión
O(nortepagregistro(pag)){\displaystyle O\left({\frac {n}{p}}\log(p)\right)}para búsqueda binaria para todas las claves
O(nortepag){\displaystyle O\left({\frac {n}{p}}\right)}enviar claves al bucket

Clasificar los cubos.

O(do(nortepag)){\displaystyle O\left(c\left({\frac {n}{p}}\right)\right)}dóndedo(norte){\displaystyle c(n)}es la complejidad del método de ordenación secuencial subyacente. [ 1 ] A menudodo(norte)=norteregistro(norte){\displaystyle c(n)=n\log(n)}.

El número de comparaciones realizadas por este algoritmo se aproxima al óptimo teórico de la información.registro2(norte¡){\displaystyle \log _{2}(n!)}para secuencias de entrada grandes. En experimentos realizados por Frazer y McKellar, el algoritmo necesitó un 15 % menos de comparaciones que quicksort.

Muestreo de los datos

Los datos pueden muestrearse mediante diferentes métodos. Algunos de estos métodos incluyen:

  1. Seleccione muestras espaciadas uniformemente.
  2. Seleccione muestras al azar.

sobremuestreo

La relación de sobremuestreo determina cuántas veces más elementos de datos se extraen como muestras, antes de determinar los divisores. El objetivo es obtener una buena representación de la distribución de los datos. Si los valores de los datos están ampliamente distribuidos, es decir, no hay muchos valores duplicados, entonces una relación de muestreo pequeña es suficiente. En otros casos donde hay muchos duplicados en la distribución, será necesaria una relación de sobremuestreo mayor. En el caso ideal, después del paso 2, cada cubo contienenorte/pag{\displaystyle n/p}elementos. En este caso, ningún cubo tarda más en ordenarse que los demás, porque todos los cubos tienen el mismo tamaño.

Después de tirark{\displaystyle k}veces más muestras de las necesarias, las muestras se clasifican. Posteriormente, los divisores utilizados como límites de cubeta son las muestras en la posiciónk,2k,3k,,(pag1)k{\displaystyle k,2k,3k,\dots ,(p-1)k}de la secuencia de muestras (junto con{\displaystyle -\infty }y{\displaystyle \infty }como límites izquierdo y derecho para los cubos más a la izquierda y más a la derecha respectivamente). Esto proporciona una mejor heurística para buenos divisores que simplemente seleccionarpag{\displaystyle p}divisores aleatoriamente.

Estimación del tamaño del cubo

Con el tamaño de muestra resultante, se puede estimar el tamaño esperado del cubo y, especialmente, la probabilidad de que un cubo supere un cierto tamaño. A continuación se mostrará que para un factor de sobremuestreo deSΘ(registronorteϵ2){\displaystyle S\in \Theta \left({\dfrac {\log n}{\epsilon ^{2}}}\right)}la probabilidad de que ningún cubo tenga más de(1+ϵ)nortepag{\displaystyle (1+\epsilon )\cdot {\dfrac {n}{p}}}elementos es mayor que11norte{\displaystyle 1-{\dfrac {1}{n}}}.

Para demostrar esto, dejemos quemi1,,minorte{\displaystyle \langle e_{1},\dots ,e_{n}\rangle }sea ​​la entrada como una secuencia ordenada. Para que un procesador obtenga más de(1+ϵ)norte/pag{\displaystyle (1+\epsilon )\cdot n/p}elementos, debe existir una subsecuencia de la entrada de longitud(1+ϵ)norte/pag{\displaystyle (1+\epsilon )\cdot n/p}de las cuales se selecciona un máximo de S muestras. Estos casos constituyen la probabilidadPAGfallar{\displaystyle P_{\text{fail}}}Esto puede representarse como la variable aleatoria: incógnitai:={1,si simij,,mij+(1+ϵ)nortepag0,de lo contrario,incógnita:=i=0Spag1incógnitai{\displaystyle X_{i}:={\begin{cases}1,&{\text{if }}s_{i}\in \left\langle e_{j},\dots ,e_{j}+(1+\epsilon )\cdot {\dfrac {n}{p}}\right\rangle \\0,&{\text{otherwise}}\end{cases}},X:=\sum _{i=0}^{S\cdot p-1}X_{i}}

Para el valor esperado deincógnitai{\displaystyle X_{i}}contiene: mi(incógnitai)=PAG(incógnitai=1)=1+ϵpag{\displaystyle E(X_{i})=P(X_{i}=1)={\dfrac {1+\epsilon }{p}}}

Esto se utilizará para estimarPAGfallar{\displaystyle P_{\text{fail}}}: PAG(incógnita<S)PAG(incógnita<(1ϵ2)S)=PAG(incógnita<(1ϵ)mi(incógnita)){\displaystyle P(X<S)\approx P(X<(1-\epsilon ^{2})S)=P(X<(1-\epsilon )E(X))}

Utilizando ahora la cota de Chernoff , se puede demostrar que: PAGfallar=nortePAG(incógnita<S)norteexp(ϵ2S2)norte1norte2 para S4ϵ2lnnorte{\displaystyle P_{\text{fail}}=n\cdot P(X<S)\leq n\cdot \exp \left({\dfrac {-\epsilon ^{2}\cdot S}{2}}\right)\leq n\cdot {\dfrac {1}{n^{2}}}{\text{ for }}S\geq {\dfrac {4}{\epsilon ^{2}}}\ln n}

Muchas llaves idénticas

En caso de muchas claves idénticas, el algoritmo pasa por muchos niveles de recursión donde se ordenan las secuencias, porque toda la secuencia consta de claves idénticas. Esto se puede contrarrestar introduciendo cubetas de igualdad. Los elementos iguales a un pivote se ordenan en su respectiva cubeta de igualdad, lo que se puede implementar con solo una rama condicional adicional. Las cubetas de igualdad no se ordenan más. Esto funciona, ya que las claves que aparecen más denorte/k{\displaystyle n/k}Es probable que estos momentos se conviertan en puntos de inflexión.

Usos en sistemas paralelos

Ejemplo de Samplesort paralelo enpag=3{\displaystyle p=3}procesadores y un factor de sobremuestreo dek=3{\displaystyle k=3}.

Samplesort se usa frecuentemente en sistemas paralelos, incluyendo sistemas distribuidos como máquinas paralelas síncronas masivas . [ 6 ] [ 4 ] [ 7 ] Debido a la cantidad variable de divisores (a diferencia de Quicksort , que solo tiene un pivote ), Samplesort es muy adecuado e intuitivo para la paralelización y la escalabilidad. Además, Samplesort también es más eficiente en el uso de caché que implementaciones de, por ejemplo, Quicksort.

La paralelización se implementa dividiendo la ordenación para cada procesador o nodo, donde el número de cubetas es igual al número de procesadores.pag{\displaystyle p}El algoritmo Samplesort es eficiente en sistemas paralelos porque cada procesador recibe aproximadamente el mismo tamaño de cubeta.norte/pag{\displaystyle n/p}Dado que los cubos se ordenan simultáneamente, los procesadores completarán la ordenación aproximadamente al mismo tiempo, evitando así que un procesador tenga que esperar a los demás.

En los sistemas distribuidos , los divisores se eligen tomandok{\displaystyle k}elementos en cada procesador, ordenando el resultadokpag{\displaystyle kp}elementos con un algoritmo de ordenación distribuida, tomando cadak{\displaystyle k}-ésimo elemento y transmitir el resultado a todos los procesadores. Esto cuestaTclasificar(kpag,pag){\displaystyle T_{\text{sort}}(kp,p)}para clasificar elkpag{\displaystyle kp}elementos enpag{\displaystyle p}procesadores, así como TAllgather(pag,pag){\displaystyle T_{\text{allgather}}(p,p)}para distribuir elpag{\displaystyle p}divisores elegidos parapag{\displaystyle p}procesadores.

Con los divisores resultantes, cada procesador coloca sus propios datos de entrada en depósitos locales. Esto llevaO(norte/pagregistropag){\displaystyle {\mathcal {O}}(n/p\log p)}con búsqueda binaria . Posteriormente, los cubos locales se redistribuyen a los procesadores. Procesadori{\displaystyle i}consigue los cubos localesbi{\displaystyle b_{i}}de todos los demás procesadores y los ordena localmente. La distribución tomaTtodos a todos(norte,pag){\displaystyle T_{\text{all-to-all}}(N,p)}tiempo, dondenorte{\displaystyle N}es el tamaño del cubo más grande. La clasificación local tomaTordenación local(norte){\displaystyle T_{\text{localsort}}(N)}.

Los experimentos realizados a principios de la década de 1990 en supercomputadoras Connection Machine demostraron que samplesort era particularmente eficaz para ordenar grandes conjuntos de datos en estas máquinas, debido a que genera poca sobrecarga de comunicación entre procesadores. [ 8 ] En las GPU más recientes , el algoritmo puede ser menos eficaz que sus alternativas. [ 9 ]

Implementación eficiente de Samplesort

Ejemplo animado de Super Scalar Samplesort. En cada paso, los números que se comparan se marcan en azul y los que se leen o escriben se marcan en rojo.

Como se describió anteriormente, el algoritmo de ordenación por muestreo divide los elementos según los divisores seleccionados. En el artículo "Super Scalar Sample Sort" se propone una estrategia de implementación eficiente. [ 5 ] La implementación propuesta en el artículo utiliza dos matrices de tamañonorte{\displaystyle n}(el array original que contiene los datos de entrada y uno temporal) para una implementación eficiente. Por lo tanto, esta versión de la implementación no es un algoritmo in situ.

En cada paso de la recursión, los datos se copian al otro array de forma particionada. Si los datos se encuentran en el array temporal en el último paso de la recursión, se copian de nuevo al array original.

Determinación de los cubos

En un algoritmo de ordenación basado en comparaciones, la operación de comparación es la parte más crítica en términos de rendimiento. En Samplesort, esto corresponde a determinar el cubo para cada elemento. Esto requiereregistrok{\displaystyle \log k}tiempo para cada elemento.

El algoritmo Super Scalar Sample Sort utiliza un árbol de búsqueda equilibrado que se almacena implícitamente en una matriz t . La raíz se almacena en 0, el sucesor izquierdo deti{\displaystyle t_{i}}se almacena ent2i{\displaystyle t_{2i}}y el sucesor correcto se almacena ent2i+1{\displaystyle t_{2i+1}}Dado el árbol de búsqueda t , el algoritmo calcula el número de cubeta j del elementoai{\displaystyle a_{i}}de la siguiente manera (suponiendoai>tj{\displaystyle a_{i}>t_{j}}se evalúa como 1 si es verdadero y 0 en caso contrario):

j := 1 repetir log 2 ( p ) veces j := 2 j + ( a > t j ) j := jp + 1

Dado que el número de cubetas k se conoce en tiempo de compilación, el compilador puede desenrollar este bucle. La operación de comparación se implementa con instrucciones predicadas . Por lo tanto, no se producen predicciones erróneas de bifurcación , lo que ralentizaría significativamente la operación de comparación.

Particionamiento

Para una partición eficiente de los elementos, el algoritmo necesita conocer de antemano el tamaño de los cubos. Para particionar los elementos de la secuencia e insertarlos en el array, necesitamos conocer el tamaño de los cubos con anticipación. Un algoritmo simple podría contar el número de elementos de cada cubo. Luego, los elementos podrían insertarse en el otro array en el lugar correcto. De esta manera, es necesario determinar el cubo para cada elemento dos veces (una vez para contar el número de elementos en un cubo y otra para insertarlos).

Para evitar esta duplicación de comparaciones, Super Scalar Sample Sort utiliza una matriz adicional.o{\displaystyle o}(llamado oráculo) que asigna cada índice de los elementos a un cubo. Primero, el algoritmo determina el contenido deo{\displaystyle o}determinando el cubo para cada elemento y los tamaños de los cubos, y luego colocando los elementos en el cubo determinado poro{\displaystyle o}. La matrizo{\displaystyle o}también genera costos de almacenamiento, pero como solo necesita almacenarnorteregistrok{\displaystyle n\cdot \log k}bits, estos costos son pequeños en comparación con el espacio del arreglo de entrada.

ordenación de muestras in situ

Una desventaja clave de la implementación eficiente de Samplesort mostrada anteriormente es que no es in situ y requiere un segundo arreglo temporal del mismo tamaño que la secuencia de entrada durante la ordenación. Las implementaciones eficientes de, por ejemplo, quicksort son in situ y, por lo tanto, más eficientes en cuanto a espacio. Sin embargo, Samplesort también puede implementarse in situ. [ 10 ]

El algoritmo in situ se divide en cuatro fases:

  1. Muestreo que es equivalente al muestreo en la implementación eficiente mencionada anteriormente.
  2. La clasificación local en cada procesador agrupa la entrada en bloques de tal manera que todos los elementos de cada bloque pertenecen al mismo grupo, pero los grupos no son necesariamente contiguos en la memoria.
  3. La permutación de bloques ordena los bloques de forma globalmente correcta.
  4. La limpieza desplaza algunos elementos que se encuentran en los bordes de los cubos.

Una desventaja evidente de este algoritmo es que lee y escribe cada elemento dos veces: una en la fase de clasificación y otra en la fase de permutación de bloques. Sin embargo, el algoritmo es hasta tres veces más rápido que otros algoritmos in situ de última generación y hasta 1,5 veces más rápido que otros algoritmos secuenciales de última generación. Dado que el muestreo ya se ha tratado anteriormente, las tres etapas posteriores se detallarán más adelante.

Clasificación local

En un primer paso, la matriz de entrada se divide enpag{\displaystyle p}franjas de bloques de igual tamaño, una para cada procesador. Cada procesador asigna ademásk{\displaystyle k}Se utilizan búferes del mismo tamaño que los bloques, uno para cada cubeta. Posteriormente, cada procesador escanea su franja y mueve los elementos al búfer de la cubeta correspondiente. Si un búfer está lleno, se escribe en la franja del procesador, comenzando desde el principio. Siempre hay al menos un búfer vacío, ya que para que se escriba en un búfer (es decir, que esté lleno), se debe escanear al menos un búfer completo con más elementos que los que se han escrito. Por lo tanto, cada bloque completo contiene elementos de la misma cubeta. Durante el escaneo, se mantiene un registro del tamaño de cada cubeta.

permutación de bloques

En primer lugar, se realiza una operación de suma de prefijos que calcula los límites de los cubos. Sin embargo, dado que solo se mueven bloques completos en esta fase, los límites se redondean a un múltiplo del tamaño del bloque y se asigna un único búfer de desbordamiento. Antes de comenzar la permutación de bloques, es posible que algunos bloques vacíos deban moverse al final de su cubo. Posteriormente, se asigna un puntero de escritura.wi{\displaystyle w_{i}}está configurado al inicio del cubobi{\displaystyle b_{i}}submatriz para cada cubo y un puntero de lecturari{\displaystyle r_{i}}está configurado en el último bloque no vacío del cubo.bi{\displaystyle b_{i}}submatriz para cada cubo.

Para limitar la contención de trabajo, a cada procesador se le asigna un depósito primario diferente.bpagrimetro{\displaystyle b_{prim}}y dos búferes de intercambio que pueden contener un bloque cada uno. En cada paso, si ambos búferes de intercambio están vacíos, el procesador decrementa el puntero de lectura.rpagrimetro{\displaystyle r_{prim}}de su cubo principal y lee el bloque enrpagrimetro1{\displaystyle r_{prim-1}}y lo coloca en uno de sus búferes de intercambio. Después de determinar el cubo de destinobdmist{\displaystyle b_{dest}}del bloque al clasificar el primer elemento del bloque, incrementa el puntero de escriturawdmist{\displaystyle w_{dest}}, lee el bloque enwdmist1{\displaystyle w_{dest-1}}en el otro búfer de intercambio y escribe el bloque en su cubo de destino. Siwdmist>rdmist{\displaystyle w_{dest}>r_{dest}}Los búferes de intercambio vuelven a estar vacíos. De lo contrario, el bloque que queda en los búferes de intercambio debe insertarse en su depósito de destino.

Si todos los bloques del subconjunto del cubo principal de un procesador se encuentran en el cubo correcto, se elige el siguiente cubo como cubo principal. Si un procesador ya ha elegido todos los cubos como cubo principal una vez, el procesador ha finalizado.

Limpieza

Dado que en la fase de permutación de bloques solo se movieron bloques completos, es posible que algunos elementos aún se encuentren mal ubicados cerca de los límites de los cubos. Como debe haber suficiente espacio en el arreglo para cada elemento, estos elementos mal ubicados se pueden mover a espacios vacíos de izquierda a derecha, considerando finalmente el búfer de desbordamiento.

Véase también

Referencias

  1. 1 2 "Samplesort usando la biblioteca paralela adaptativa de plantillas estándar" (PDF) (Informe técnico). Universidad de Texas A&M.
  2. Grama, Ananth; Karypis, George; Kumar, Vipin (2003). "9.5 Bucket and Sample Sort" . Introducción a la computación paralela (2.ª ed.). Addison-Wesley. ISBN  0-201-64865-2Archivado del original el 13/12/2016 . Consultado el 28/10/2014 .
  3. 1 2 Frazer, WD; McKellar, AC (1970-07-01). "Samplesort: Un enfoque de muestreo para la clasificación de árboles de almacenamiento mínimo" . Journal of the ACM . 17 (3): 496– 507. doi : 10.1145/321592.321600 . S2CID 16958223 . 
  4. 1 2 Hill, Jonathan MD; McColl, Bill; Stefanescu, Dan C.; Goudreau, Mark W.; Lang, Kevin; Rao, Satish B.; Suel, Torsten; Tsantilas, Thanasis; Bisseling, Rob H. (1998). "BSPlib: La biblioteca de programación BSP". Computación paralela . 24 (14): 1947– 1980. CiteSeerX 10.1.1.48.1862 . doi : 10.1016/S0167-8191(98)00093-3 . 
  5. 1 2 Sanders, Peter; Winkel, Sebastian (14 de septiembre de 2004). "Super Scalar Sample Sort". Algorithms – ESA 2004. Lecture Notes in Computer Science. Vol. 3221. pp. 784–796 . CiteSeerX 10.1.1.68.9881 . doi : 10.1007/978-3-540-30140-0_69 . ISBN    978-3-540-23025-0.
  6. Gerbessiotis, Alexandros V.; Valiant, Leslie G. (1992). "Algoritmos paralelos directos síncronos en masa". J. Parallel and Distributed Computing . 22 : 22– 251. CiteSeerX 10.1.1.51.9332 . 
  7. Hightower, William L.; Prins, Jan F.; Reif, John H. (1992). Implementaciones de ordenación aleatoria en grandes máquinas paralelas (PDF) . Simposio de la ACM sobre algoritmos y arquitecturas paralelas.
  8. Blelloch, Guy E. ; Leiserson, Charles E. ; Maggs, Bruce M.; Plaxton, C. Gregory; Smith, Stephen J.; Zagha, Marco (1991). Una comparación de algoritmos de ordenación para la Connection Machine CM-2 . Simposio ACM sobre algoritmos y arquitecturas paralelas. CiteSeerX 10.1.1.131.1835 . 
  9. Satish, Nadathur; Harris, Mark; Garland, Michael. Diseño de algoritmos de ordenación eficientes para GPU multinúcleo . Actas del Simposio Internacional de Procesamiento Paralelo y Distribuido de la IEEE. CiteSeerX 10.1.1.190.9846 . 
  10. Axtmann, Michael; Witt, Sascha; Ferizovic, Daniel; Sanders, Peter (2017). "In-Place Parallel Super Scalar Samplesort (IPSSSSo)" . 25th Annual European Symposium on Algorithms (ESA 2017) . 87 (Leibniz International Proceedings in Informatics (LIPIcs)): 9:1–9:14. doi : 10.4230/LIPIcs.ESA.2017.9 .

El método de clasificación de muestras de Frazer y McKellar y sus derivados:

  • El artículo original de Frazer y McKellar
  • DOI.org
  • DOI.org

Adaptado para su uso en ordenadores paralelos:

  • http://citeseer.ist.psu.edu/91922.html
  • http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.49.214