¿Es posible acelerar la IO de python?

Considere este progtwig de python:

import sys lc = 0 for line in open(sys.argv[1]): lc = lc + 1 print lc, sys.argv[1] 

Al ejecutarlo en mi archivo de texto de 6 GB, se completa en ~ 2 minutos.

Pregunta: ¿Es posible ir más rápido?

Tenga en cuenta que el mismo tiempo es requerido por:

 wc -l myfile.txt 

Por lo tanto, sospecho que la respuesta a mi pregunta es simplemente un simple “no”.

Tenga en cuenta también que mi progtwig real está haciendo algo más interesante que solo contar las líneas, así que proporcione una respuesta genérica, no trucos de conteo de líneas (como mantener un metadata de conteo de líneas en el archivo)

PD: etiqueté “linux” esta pregunta, porque solo me interesan las respuestas específicas de linux. Siéntase libre de dar respuestas del sistema operativo, o incluso de otro sistema operativo, si las tiene.

Ver también la pregunta de seguimiento.

No puede obtener más rápido que la velocidad máxima de lectura del disco.

Para alcanzar la velocidad máxima del disco, puede utilizar los dos consejos siguientes:

  1. Lee el archivo con un búfer grande. Esto se puede codificar “manualmente” o simplemente usando io.BufferedReader (disponible en python2.6 +).
  2. Haga la nueva línea contando en otro hilo, en paralelo.

Tirar hardware al problema.

Como señala gs, su cuello de botella es la tasa de transferencia del disco duro. Entonces, no, no puedes usar un algoritmo mejor para mejorar tu tiempo, pero puedes comprar un disco duro más rápido.

Edit: Otro buen punto por gs; También puede utilizar una configuración RAID para mejorar su velocidad. Esto se puede hacer con hardware o software (por ejemplo, OS X , Linux , Windows Server , etc.).


Equación gobernante

(Amount to transfer) / (transfer rate) = (time to transfer)

(6000 MB) / (60 MB/s) = 100 seconds

(6000 MB) / (125 MB/s) = 48 seconds


Soluciones de hardware

El ioDrive Duo es supuestamente la solución más rápida para un entorno corporativo, y “estará disponible en abril de 2009”.

O puede revisar el disco duro WD Velociraptor (10,000 rpm).

Además, escucho que el Seagate Cheetah es una buena opción (15,000 rpm con una tasa de transferencia sostenida de 125MB / s).

El truco no es hacer que los electrones se muevan más rápido (eso es difícil de hacer) sino hacer más trabajo por unidad de tiempo.

Primero, asegúrese de que la lectura de su archivo de 6 GB esté vinculada a E / S, no a CPU.

Si está enlazado a E / S, tenga en cuenta el patrón de diseño “Abanico de salida”.

  • Un proceso de padres engendra un montón de niños.

  • El padre lee el archivo de 6Gb y distribuye filas a los niños escribiendo en sus tuberías STDIN. El tiempo de lectura de 6GB se mantendrá constante. El tratamiento de la fila debe implicar el menor procesamiento padre posible. Se deben utilizar filtros o conteos muy simples.

    Un conducto es un canal en memoria para la comunicación. Es un buffer compartido con un lector y un escritor.

  • Cada niño lee una fila de STDIN y hace el trabajo apropiado. Cada niño probablemente debería escribir un archivo de disco simple con los resultados finales (resumidos, reducidos). Más tarde, los resultados en esos archivos se pueden consolidar.

llano “no”.

Has alcanzado la velocidad máxima del disco.

Quiero decir, podrías hacer un mapa del archivo, o leerlo en fragmentos binarios, y usar .count('\n') o algo así. Pero eso es poco probable que dé grandes mejoras.

Si asume que un disco puede leer 60 MB / s, necesitará 6000/60 = 100 segundos, lo que equivale a 1 minuto y 40 segundos. No creo que puedas obtener más rápido porque el disco es el cuello de botella.

Tenga en cuenta que Python I / O se implementa en C, por lo que no hay mucha suerte en acelerarlo aún más.

como otros han dicho – “no”

Casi todo tu tiempo se gasta esperando por IO. Si esto es algo que necesita hacer más de una vez, y tiene una máquina con toneladas de memoria RAM, puede mantener el archivo en la memoria. Si su máquina tiene 16 GB de RAM, tendrá 8 GB disponibles en / dev / shm para jugar.

Otra opción: si tiene varias máquinas, este problema es trivial para paralelizar. Divídalo entre varias máquinas, cada una de ellas cuenta sus nuevas líneas y agrega los resultados.

2 minutos parece correcto para leer un archivo completo de 6 gb. Realmente no hay mucho que puedas hacer con el algoritmo o el sistema operativo para acelerar las cosas. Creo que tienes dos opciones:

  1. Tirar el dinero en el problema y obtener mejor hardware. Probablemente la mejor opción si este proyecto es para tu trabajo.

  2. No lea todo el archivo. No sé qué intentas hacer con los datos, así que quizás no tengas otra opción que leer todo el asunto. Por otro lado, si está escaneando todo el archivo en busca de una cosa en particular, tal vez sea útil colocar algunos metadatos al principio.