¿Qué algoritmo de clasificación es eficiente para grandes datos y por qué?

Oh chico. El antiguo cómo clasifico el big data. Bueno, dado que he estado involucrado en este tipo de cosas, podría intentarlo.

En primer lugar, las entrevistas técnicas 101 nos dicen que hagamos preguntas aclaratorias. Realmente no especificaste:

  • ¿Qué tipo de datos estábamos clasificando? (¿números? cadenas? filas de la base de datos?)
  • ¿Cuántos datos son datos grandes ? Gigabytes? Petabytes?
  • ¿Cuántas y qué tipo de máquinas tenemos a nuestra disposición?
  • ¿Cuánta memoria tenemos?
  • ¿Cuánto almacenamiento tenemos?
  • ¿Qué tipo de almacenamiento tenemos? El almacenamiento local rápido (SSD), el almacenamiento local lento, el almacenamiento en red, etc., todos vienen a la mente y pueden desempeñar un papel en la decisión de qué estrategia queremos usar.

Entonces, sin respuestas a estas preguntas, realmente no podemos diseñar un algoritmo. Aquí hay una idea. Si me dijeras que estabas clasificando un flujo casi infinito de números enteros , no sudaría. ¿Por qué? Porque la naturaleza nos dio el tipo Radix. Con Radix sort, estás ordenando en tiempo lineal y puedes elegir cuánta memoria gastas. Si me diera 2048 B de memoria para almacenar mis 256 cubos de conteos de 8 bytes, y suficiente almacenamiento rápido, no necesariamente en una máquina, tal vez incluso en la Nube, terminaríamos con esto en poco tiempo.

Pero, si desea ordenar datos genéricos, como las filas de la base de datos, las cosas pueden volverse un poco más complicadas. En primer lugar, no más clasificación en tiempo lineal. Esa es la menor de tus preocupaciones. Obviamente, está limitado por la memoria disponible y asume que tiene “suficiente” almacenamiento para operaciones intermedias y salida de datos.

Sus principios principales son: cargue todo lo que pueda en la memoria para que pueda ordenar rápidamente (entiéndalo, ja, ja, estoy implicando una clasificación rápida aquí) y asegúrese de distribuir estas cargas de la manera más equitativa posible en todos procesadores disponibles. Si golpeas un OOM (excepción de falta de memoria), bueno, supongo que solo tendrás que derramar lo que has ordenado hasta ahora para liberar memoria disponible y consumir más. Al final de todo, simplemente recoge todo lo que has derramado y combínalo en una secuencia bien ordenada.

Entonces, teniendo eso en mente, dibujemos el algoritmo:

Para cada hilo disponible:

  1. Cargar datos en la memoria
    1. Si nunca llegas a un OOM, entonces supongo que es tu día de suerte porque pareces tener toda la memoria del mundo, así que sigue cargando.
    2. Si llega a un OOM, entonces clasifique todo lo que ha recopilado hasta ahora utilizando un buen algoritmo como Quick Sort o, mejor aún, un híbrido que tenga en cuenta los casos teóricos de Quick Sort.
  2. Ordene sus datos en memoria.

De acuerdo, sus hilos han ordenado todo lo que recolectaron, y eso está en la memoria o se ha derramado en algún almacenamiento. Si todo está en la memoria, entonces solo tienes que combinar un montón de arreglos ordenados, ¡woohoo! Sin embargo, estamos clasificando algunos datos muy grandes, así que supongo que ese no es el caso.

Entonces, ahora sabemos que tenemos un montón de archivos que contienen partes ordenadas de la gran secuencia y comenzamos a fusionar cosas. Tenga en cuenta que esto no es una combinación de clasificación, sino que simplemente combina dos matrices ordenadas en una sola matriz ordenada. Entonces, de nuevo,

Para cada hilo disponible:

  1. Elija un par de secuencias ordenadas que viven en archivos, ahora. Observe que realmente no necesita cargarlos todos en la memoria. Si todos comenzaron a cargar todo en la memoria, sabes que te quedarás sin batería nuevamente. Después de todo, ya lo hiciste, una vez, ¿recuerdas? Entonces, con solo un poco de memoria extra, escanee los archivos derramados y combínelos en un archivo de salida.
  2. Haga eso hasta que solo le quede un gran archivo ordenado, combinado.

Entonces, si tuviera N archivos que contienen secuencias ordenadas derramadas, podría dividirlas en N / 2 pares. Deje que tantos hilos como sea posible mastiquen un par. Si tiene más de N / 2 subprocesos, terminará teniendo archivos N / 2 después de la primera etapa. Luego N / 4 después del segundo. Eventualmente, tendrás solo uno. Si tiene menos hilos que pares, entonces todos sus hilos estarán involucrados en la fusión, pero no podrá procesar todos los pares al mismo tiempo. Eso no es un problema, nadie dice que las secuencias de salida deben ser del mismo tamaño en primer lugar. De todos modos, siempre hay algo para hacer los hilos, no hay razón para dejarlos inactivos.

Entonces, ahora que le queda un gran archivo lleno de datos ordenados, simplemente escanee, engullendo un trozo a la vez y pasándolo por la secuencia. Escanee en paralelo, si su sistema lo permite (es decir, si tiene algún flujo descendente de búfer que combina N flujos de entrada), no me importa.

Entonces, eso sería todo para el caso genérico. Para los más especializados, como el que describí lejos, muy arriba, con enteros, existen soluciones más eficientes que son posibles debido a la naturaleza específica de los datos.

Bastante simple, ¿eh?

Si te refieres a “datos grandes”, ya que es imposible encajar todo en la RAM de una vez, entonces la idea básica es usar el tipo de fusión, ya que se puede implementar para dividir los datos y solo mantener porciones de ellos en la RAM. De hecho, esto se usó hace varias décadas al clasificar las unidades de cinta. Clasificación de fusión externa. Como muestra actual, el comando de clasificación Unix se implementa utilizando este método: [TECH] Detalles algorítmicos del comando de clasificación UNIX.

El principio principal es una forma de “dividir y conquistar” … es decir, dividir los datos en fragmentos más manejables, ordenarlos y luego fusionarlos de nuevo en un todo.

Sin embargo, ¿necesita ordenar, o se preferiría un índice? En casi todos los sistemas de bases de datos, los datos reales se dejan sin clasificar, y se aplica un esquema de indexación que almacena una estructura de índice en uno de los muchos métodos ordenados (generalmente alguna forma de estructura de árbol, aunque a veces también se usan tablas hash). Esto tiene algunos beneficios sobre una clasificación estándar de los datos:

  • Puede ordenar efectivamente los mismos datos utilizando múltiples atributos, sin necesidad de modificar los datos en sí. Por ejemplo, un índice en un valor clave, otro en una fecha, otro en un nombre, etc.
  • Dado que el índice sería mucho más pequeño que los datos, se pueden cargar porciones más grandes directamente en la RAM. También los cambios debidos a la clasificación del índice significan mucho menos E / S (es decir, la reducción de la velocidad real en grandes datos) que hacer lo mismo en el conjunto de datos completo. Es decir, las reorganizaciones debido a adiciones y eliminaciones se pueden hacer más rápido.
  • Algunos esquemas de indexación proporcionan un rendimiento de búsqueda / inserción aún mejor que una búsqueda binaria en una lista ordenada; por ejemplo, las tablas hash pueden proporcionar una búsqueda O (1).

More Interesting

¿Qué función se usa para aceptar números aleatorios entre límite inferior y superior en C?

Cómo dominar las estructuras de datos y los algoritmos (DSA) para mejorar mis habilidades de resolución de problemas que eventualmente serán útiles en las entrevistas

¿Cómo se escriben los algoritmos de espacio?

¿Qué es mejor, resolver menos problemas por su cuenta o más problemas usando sugerencias?

¿Cómo puedo diseñar una función hash que elija aleatoriamente 16 bits de un número de 32 bits?

¿Hay alguna manera de extraer la palabra principal de una lista de sinónimos que representa la lista?

Cómo hacer un bot de chat usando Python implementando algoritmos de aprendizaje automático (como SVM, Naive Bayes, Random Forest, etc.)

¿Cuál es la operación que tiene la constante más pequeña?

¿Existe un algoritmo para contar el número de subsecuencias divisibles por 8?

¿Cuántas comparaciones se requieren para fusionar 4 archivos ordenados de 35 registros en un solo archivo ordenado?

¿Cuál es la mejor manera de extrapolar una señal dispersa que proviene de un filtro de Kalman?

¿Por qué una clasificación rápida es mejor que una clasificación múltiple?

¿Es posible simular / emular / codificar el poder de pensamiento de una CPU en una GPU?

¿Por qué puede verse la secuencia de Fibonacci como un algoritmo dinámico y por qué tiene un mal tiempo de ejecución?

¿Qué estructura de datos es adecuada para almacenar una gran cantidad de cadenas en Java?