2009-05-11 18 views
11

consideran este programa en Python:¿Es posible acelerar Python IO?

import sys 

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

print lc, sys.argv[1] 

Correr en mi archivo de texto 6 GB, que se completa en 2 minutos ~.

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

Tenga en cuenta que al mismo tiempo se requiere por:

wc -l myfile.txt 

así, sospecho que la anwer a mi quesion es sólo un simple "no".

Tenga en cuenta también que mi verdadero programa está haciendo algo más interesante que un simple recuento de las líneas, así que por favor dar una respuesta genérica, no Hoja de conteo-tricks (como mantener una metadatos número de líneas en el archivo)

PD: etiqueté "linux" esta pregunta, porque solo estoy interesado en respuestas específicas de Linux. Siéntete libre de dar respuestas de OS-agnóstico, o incluso de otro sistema operativo, si las tienes.

Véase también la llanura follow-up question

+3

echar un vistazo para una discusión muy similar aquí: http://stackoverflow.com/questions/845058/how-to-get-line-count-cheaply-in-python – SilentGhost

+3

Probablemente la mayor parte del tiempo aquí se gasta esperando en el disco. –

+0

Llego tarde a la fiesta, pero para archivos grandes "sed -n '$ =' nombre de archivo" es más rápido que "wc -l" – philshem

Respuesta

3

No puede obtener una velocidad de lectura de disco más rápida que la máxima.

Con el fin de alcanzar la velocidad de disco máximo que puede utilizar las dos puntas siguientes:

  1. leer el archivo con una gran amortiguación. Esto puede codificarse "manualmente" o simplemente usando io.BufferedReader (disponible en python2.6 +).
  2. Haga el recuento de línea nueva en otra secuencia, en paralelo.
+2

-1 no veo cómo acelerar el recuento de línea nueva en otro subproceso. Simplemente ralentizará las cosas. Esperar hilos no te hace esperar más rápido. – nosklo

+4

Normalmente, estarías en lo cierto. Sin embargo, en este caso, la lectura de hilo del archivo esperará a la E/S mientras que el otro hilo analizará las nuevas líneas. De esta forma, el hilo del lector no esperará a que el hilo del analizador analice las nuevas líneas entre las lecturas consecuentes. – Barakando

+0

Estoy aceptando esta respuesta, aunque en este caso particular no vale la pena, ya que el trabajo por línea es muy bajo y ya voy a la máxima velocidad. Ver también la pregunta de seguimiento, para más detalles. – Davide

5

"no".

Ha alcanzado prácticamente la velocidad máxima de disco.

Quiero decir, podría mmap el archivo, o leerlo en fragmentos binarios, y usar .count('\n') o algo así. Pero es poco probable que proporcione mejoras importantes.

4

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

+1

¿De dónde vienen esos 20 en su cálculo? ¿Quisiste decir 6000/60 = 100? 60 no 20, ¿verdad? –

+0

Primero quise calcularlo con 20MB/s, pero luego pensé que esto era demasiado lento. –

1

como otros han dicho - "no"

Casi la totalidad de su tiempo se dedica a la espera de IO. Si esto es algo que necesita hacer más de una vez, y tiene una máquina con toneladas de 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ídelo entre varias máquinas, cada una cuenta sus nuevas líneas y agrega los resultados.

1

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

+2

Puede escribir código C perfectamente malo y lento, por lo tanto, si está escrito en C no garantiza que sea rápido. Y puede haber gastos generales (por ejemplo, para interpretar el bytecode, para leer por filas e iterar, etc.) que pueden ralentizarlo. – Davide

12

Lanza el hardware al problema.

Como gs señaló, su cuello de botella es la velocidad 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.

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


Administración Ecuación

(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

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

O puede consultar el disco duro WD Velociraptor (10.000 rpm).

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

+3

Los RAID podrían ser mucho más rápidos. –

7

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

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

Si está vinculado a E/S, considere el patrón de diseño "Fan-Out".

  • Un proceso principal genera un grupo de niños.

  • El elemento principal lee el archivo de 6 Gb y distribuye las filas a los niños escribiendo en las tuberías de STDIN. El tiempo de lectura de 6GB permanecerá constante. La negociación de filas debe implicar el menor procesamiento posible de los padres. Deben usarse filtros o conteos muy simples.

    Una tubería es un canal en la memoria para la comunicación. Es un buffer compartido con un lector y un escritor.

  • Cada niño lee una fila de STDIN y realiza el trabajo adecuado. 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.

+0

probablemente (en la tercera viñeta) quiso decir que todos los niños deberían hablar entre sí en la memoria, ya que el disco ya está muy ocupado – Davide

+0

Las tuberías * son * canales de comunicación en la memoria. –

+0

Sí, pero en su tercera viñeta escribió: "Probablemente cada niño debería escribir un archivo de disco simple". – Davide

1

2 minutos suena a la derecha para leer un archivo completo de 6 gb. No hay mucho que puedas hacer con el algoritmo o el sistema operativo para acelerar las cosas.Creo que tiene dos opciones:

  1. Tirar dinero al problema y obtener un mejor hardware. Probablemente la mejor opción si este proyecto es para su trabajo.

  2. No lea todo el archivo. No sé qué estás tratando de hacer con los datos, así que tal vez no tienes otra opción que leer todo el asunto. Por otro lado, si está escaneando todo el archivo para una cosa en particular, entonces sería útil poner algunos metadatos allí al inicio.

Cuestiones relacionadas