¿Qué cambia cuando tu entrada tiene un tamaño de giga / terabyte?

Acabo de dar mi primer paso de bebé hoy a la computación científica real hoy cuando me mostraron un conjunto de datos donde el archivo más pequeño tiene 48000 campos por 1600 filas (haplotipos para varias personas, para el cromosoma 22). Y esto se considera minúsculo.

Escribo Python, así que pasé las últimas horas leyendo sobre HDF5, y Numpy, y PyTable, pero sigo sintiendo que realmente no estoy tratando de entender lo que un conjunto de datos del tamaño de un terabyte realmente significa para mí como progtwigdor.

Por ejemplo, alguien señaló que con conjuntos de datos más grandes, resulta imposible leer todo en memoria, no porque la máquina no tenga suficiente RAM, sino porque la architecture no tiene suficiente espacio de direcciones. Me quedé boquiabierto.

¿En qué otras suposiciones he confiado en el aula que simplemente no funcionan con aportes tan grandes? ¿Qué tipo de cosas necesito para comenzar a hacer o pensar de manera diferente? (Esto no tiene que ser específico de Python.)

    Actualmente me dedico a la computación de alto rendimiento en un pequeño rincón de la industria petrolera y trabajo regularmente con conjuntos de datos de las órdenes de magnitud que le preocupan. Aquí hay algunos puntos a considerar:

    1. Las bases de datos no tienen mucha tracción en este dominio. Casi todos nuestros datos se guardan en archivos, algunos de ellos se basan en formatos de archivo de cinta diseñados en los años 70. Creo que parte de la razón por la que no se utilizan las bases de datos es histórica; 10, incluso hace 5 años, creo que Oracle y sus parientes simplemente no estaban en la tarea de administrar conjuntos de datos individuales de O (TB) y mucho menos una base de datos de miles de dichos conjuntos de datos.

      Otra razón es una discrepancia conceptual entre las reglas de normalización para el análisis y diseño efectivo de la base de datos y la naturaleza de los conjuntos de datos científicos.

      Creo (aunque no estoy seguro) que las razones de rendimiento son mucho menos persuasivas en la actualidad. Y la razón de la falta de coincidencia de conceptos probablemente también sea menos apremiante ahora que la mayoría de las principales bases de datos disponibles pueden hacer frente a conjuntos de datos espaciales que generalmente son un ajuste conceptual mucho más cercano a otros conjuntos de datos científicos. He visto un uso cada vez mayor de las bases de datos para almacenar metadatos, con algún tipo de referencia, luego, al archivo (s) que contiene los datos del sensor.

      Sin embargo, todavía estaría mirando, de hecho estoy mirando, HDF5. Tiene un par de atracciones para mí (a) es solo otro formato de archivo, así que no tengo que instalar un DBMS y luchar con sus complejidades, y (b) con el hardware adecuado puedo leer / escribir un archivo HDF5 en paralelo . (Sí, sé que también puedo leer y escribir bases de datos en paralelo).

    2. Lo que me lleva al segundo punto: cuando se trata de conjuntos de datos muy grandes, realmente necesita estar pensando en usar computación paralela. Trabajo principalmente en Fortran, uno de sus puntos fuertes es la syntax de su matriz, que encaja muy bien en una gran cantidad de computación científica; otro es el buen soporte para la paralelización disponible. Creo que Python también tiene todo tipo de soporte de paralelización, por lo que probablemente no sea una mala elección para ti.

      Claro que puede agregar paralelismo a los sistemas secuenciales, pero es mucho mejor comenzar a diseñar para el paralelismo. Para tomar solo un ejemplo: el mejor algoritmo secuencial para un problema a menudo no es el mejor candidato para la paralelización. Es posible que esté mejor utilizando un algoritmo diferente, uno que se adapte mejor a múltiples procesadores. Lo que lleva perfectamente al siguiente punto.

    3. También creo que es posible que tenga que llegar a un acuerdo con la entrega de los archivos adjuntos que tiene (si los tiene) a muchos algoritmos inteligentes y estructuras de datos que funcionan bien cuando todos sus datos residen en la memoria. Muy a menudo, tratar de adaptarlos a la situación en la que no puede obtener los datos en la memoria de una sola vez, es mucho más difícil (y menos eficaz) que la fuerza bruta y considera el archivo completo como una gran matriz.

    4. El rendimiento comienza a importar de manera seria, tanto el rendimiento de ejecución de los progtwigs como el rendimiento del desarrollador. No es que un conjunto de datos de 1TB requiera 10 veces más código que un conjunto de datos de 1GB, por lo que tiene que trabajar más rápido, sino que algunas de las ideas que necesitará implementar serán locamente complejas y probablemente tengan que ser escritas por especialistas de dominio. Es decir, los científicos con los que estás trabajando. Aquí los especialistas de dominio escriben en Matlab.

    Pero esto está pasando demasiado tiempo, es mejor que vuelva a trabajar

    En pocas palabras, las principales diferencias de la OMI:

    1. Debe saber de antemano cuál será su probable cuello de botella (E / S o CPU) y concentrarse en el mejor algoritmo e infraestructura para solucionarlo. I / O con bastante frecuencia es el cuello de botella.
    2. La elección y el ajuste fino de un algoritmo a menudo dominan cualquier otra elección realizada.
    3. Incluso los cambios modestos en los algoritmos y los patrones de acceso pueden afectar el rendimiento en órdenes de magnitud. Estarás micro-optimizando mucho. La “mejor” solución dependerá del sistema.
    4. Hable con sus colegas y otros científicos para aprovechar sus experiencias con estos conjuntos de datos. Muchos trucos no se pueden encontrar en los libros de texto.
    5. La pre-computación y el almacenamiento pueden ser extremadamente exitosos.

    Ancho de banda y E / S

    Inicialmente, el ancho de banda y la E / S a menudo son el cuello de botella. Para darle una perspectiva: en el límite teórico de SATA 3 , se tarda aproximadamente 30 minutos en leer 1 TB. Si necesita acceso aleatorio, leer varias veces o escribir, desea hacerlo en la memoria la mayor parte del tiempo o necesita algo sustancialmente más rápido (por ejemplo, iSCSI con InfiniBand ). Su sistema idealmente debería ser capaz de hacer E / S paralelas para acercarse lo más posible al límite teórico de la interfaz que esté utilizando. Por ejemplo, simplemente acceder a diferentes archivos en paralelo en diferentes procesos, o HDF5 sobre MPI-2 I / O es bastante común. Idealmente, también realiza el cálculo y la E / S en paralelo para que uno de los dos sea “gratis”.

    Agrupaciones

    Dependiendo de su caso, I / O o CPU pueden ser el cuello de botella. No importa cuál sea, se pueden lograr enormes aumentos de rendimiento con los clústeres si puede distribuir sus tareas de manera efectiva (por ejemplo, MapReduce ). Esto podría requerir algoritmos totalmente diferentes a los ejemplos típicos de libros de texto. Gastar tiempo de desarrollo aquí es a menudo el mejor tiempo empleado.

    Algoritmos

    Al elegir entre los algoritmos, la O grande de un algoritmo es muy importante, pero los algoritmos con una O grande similar pueden ser dramáticamente diferentes en rendimiento dependiendo de la localidad. Cuanto menos local sea un algoritmo (es decir, cuanto más se pierda la memoria caché y se pierda la memoria principal), peor será el rendimiento: el acceso al almacenamiento suele ser un orden de magnitud más lento que el de la memoria principal. Los ejemplos clásicos de mejoras serían el mosaico para las multiplicaciones de matriz o el intercambio de bucles .

    Computadora, lenguaje, herramientas especializadas

    Si su cuello de botella es E / S, esto significa que los algoritmos para grandes conjuntos de datos pueden beneficiarse de más memoria principal (por ejemplo, 64 bits) o lenguajes de progtwigción / estructuras de datos con menos consumo de memoria (por ejemplo, en Python __slots__ podría ser útil), porque más la memoria puede significar menos E / S por tiempo de CPU. Por cierto, los sistemas con TB de memoria principal no son desconocidos (p. Ej., Superdomes HP ).

    De manera similar, si su cuello de botella es la CPU, las máquinas, los lenguajes y los comstackdores más rápidos que le permiten usar características especiales de una architecture (por ejemplo, SIMD como SSE ) podrían boost el rendimiento en un orden de magnitud.

    La forma en que encuentre y acceda a los datos y almacene la metainformación puede ser muy importante para el rendimiento. A menudo, utilizará archivos planos o paquetes no estándar específicos del dominio para almacenar datos (por ejemplo, no un db relacional directamente) que le permitan acceder a los datos de manera más eficiente. Por ejemplo, kdb + es una base de datos especializada para grandes series de tiempo, y ROOT usa un objeto TTree para acceder a los datos de manera eficiente. Las tablas que mencionas serían otro ejemplo.

    Si bien algunos idiomas tienen una sobrecarga de memoria más baja en su tipo que en otros, eso realmente no importa para datos de este tamaño: no tiene todo el conjunto de datos en la memoria, independientemente del idioma que use, por lo que el “gasto” De Python es irrelevante aquí. Como señaló, simplemente no hay suficiente espacio de direcciones para siquiera hacer referencia a todos estos datos, y mucho menos aferrarse a ellos.

    Lo que esto significa normalmente es: a) almacenar sus datos en una base de datos, o b) agregar recursos en forma de computadoras adicionales, agregando así a su memoria y espacio de direcciones disponibles. De manera realista vas a terminar haciendo estas dos cosas. Una cosa clave que debe tener en cuenta al usar una base de datos es que una base de datos no es solo un lugar para colocar sus datos mientras no la está utilizando, puede hacer TRABAJO en la base de datos y debe intentar hacerlo. La tecnología de base de datos que utiliza tiene un gran impacto en el tipo de trabajo que puede hacer, pero una base de datos SQL, por ejemplo, está bien adaptada para realizar muchas tareas matemáticas y hacerlo de manera eficiente (por supuesto, esto significa que el diseño del esquema se convierte en una parte muy importante de su architecture en general). No solo extraiga los datos y manipúlelos solo en la memoria: intente aprovechar las capacidades de consulta computacional de su base de datos para realizar el mayor trabajo posible antes de poner los datos en la memoria de su proceso.

    Las principales suposiciones son sobre la cantidad de cpu / caché / ram / almacenamiento / ancho de banda que puede tener en una sola máquina a un precio aceptable. Hay muchas respuestas aquí en stackoverflow que aún se basan en las suposiciones anteriores de una máquina de 32 bits con 4G de RAM y alrededor de un terabyte de almacenamiento y una red de 1Gb. Con módulos de RAM DDR-3 de 16 GB a 220 Eur, 512 GB de RAM, se pueden construir 48 máquinas centrales a precios razonables. El cambio de discos duros a SSD es otro cambio importante.