Mi PC está procesando pequeños archivos .txt, sin embargo, aproximadamente 100,000 de ellos para PNL. Tarda aproximadamente 2 horas, sin embargo, ¿por qué el uso de la CPU es solo del 10%?

Su computadora está experimentando lo que se conoce como el cuello de botella de Von-Neumann.

Básicamente, esto dice que no importa cuán rápido sean sus procesadores, siempre se ven afectados por el rendimiento de la memoria.

Supongo que 100.000 archivos .txt están almacenados en el disco duro. Ya sea un SSD o un disco duro mecánico, el tiempo de acceso es del orden de milisegundos. Esto puede parecer rápido, pero el procesador funciona en el orden de nanosegundos. Entonces, por cada instancia que el archivo tiene que cargarse en la memoria, la CPU tiene que esperar. La CPU realiza alrededor de 3 mil millones de operaciones en 1 segundo. Un tiempo de espera de 5–10 milisegundos debido a HDD significa que pasará la mayor parte del tiempo esperando.

Por lo tanto, la forma de resolver esto es llevar los datos a una memoria más rápida, es decir, RAM. La memoria RAM DDR4 tiene un tiempo de acceso de alrededor de 10–15 nanosegundos, que es aproximadamente un millón de veces más rápido que el HDD.

Entonces la solución es la siguiente:

Mejor caso,

Consolide todos los archivos de 100k en un solo archivo y su programa cargará este archivo enorme al principio. El acceso al disco debe ocurrir menos veces y, dado que usted dijo que los archivos son pequeños, el ancho de banda del HDD no será un cuello de botella.

Caso ligeramente difícil / caso menos eficiente:

Paralelo a las operaciones de carga de los archivos para que los archivos se carguen más rápido.

Tu problema es E / S. Específicamente, cada vez que abre un archivo, ese archivo debe identificarse (leer y buscar directorios, uno o más), los metadatos leídos y procesados ​​(más E / S), ENTONCES los datos que desea deben leerse. Después de eso comienzas a procesar.

Hice algo similar (aunque estaba identificando y haciendo copias de seguridad de archivos que no se habían hecho antes).

Muy lento. El tamaño de mi sistema de archivos era de 16 TB, con archivos entre 1 MB y aproximadamente 5 MB. pero unos 50 millones de ellos.

Las estimaciones iniciales de cuánto tiempo tomaría, aproximadamente un mes.

La solución fue no hacerlo un archivo a la vez.

en su lugar, creé una cola donde se ingresan los archivos a procesar, luego utilicé múltiples procesos, cada uno toma un archivo y comienza a procesarlo. El primero obtiene el primer archivo, el siguiente proceso obtiene el segundo … (por lo tanto, necesita la gestión de colas para no asignar el mismo archivo a dos procesos diferentes).

También necesita el almacenamiento de los datos que extrae para permitir operaciones paralelas, pero eso depende de cómo / qué tipo de procesamiento esté haciendo.

Descubrí que en un sistema de 8 núcleos es posible ejecutar hasta 14 procesos paralelos manipulando datos. ¿Por qué? porque cuando un proceso está esperando que se abra su archivo, otro proceso procesará uno ya abierto. Las operaciones superpuestas aumentan la eficiencia del sistema (mayor carga de CPU). ¿Por qué 14 y no 16? – Ahorré algo de tiempo de CPU para la administración general y para manejar las E / S. Esto se determinó por experimento: con 16 el sistema comenzó a sacudirse, y eso desaceleró todo. 12 procesos paralelos fueron casi iguales a 14, no pude ver fácilmente ningún cambio, por lo que 14. 10 procesos paralelos fueron más lentos, 11 dieron una buena ganancia y 12 hicieron lo mismo. 13 y 14 realmente no cambiaron mucho, pero hubo algunas ganancias.

Para ti, depende de lo que estés haciendo.

En mi caso, usé dos colas. Uno para los directorios en los que se buscarán los archivos, y cada vez que se encuentra un directorio, se agrega a esta cola. La otra cola era de archivos identificados para copiar. Los procesos de salida tomarían un archivo de la segunda cola y lo copiarían (un proceso lento y relativamente hambriento de memoria). Terminé con dos procesos haciendo eso, ya que más saturaría la salida.

El resultado final fue que la fase de búsqueda e identificación no tomaría más de 45 minutos para 50 millones de archivos. La copia tardaría más dependiendo de cuántos archivos se identificaron (por lo tanto, dos procesos de los 14, dejando 12 para la búsqueda e identificación).

Incluso incluí una capacidad de punto de control que suspendió los procesos de búsqueda y los procesos de copia, luego guardé ambas colas antes de salir. El reinicio solo volvió a cargar las dos colas y comenzó los procesos. Cuando se alcanzaba el estado estable, las copias de seguridad tardarían menos de una hora.

No digo que necesite dos colas … pero depende de su procesamiento y de si puede hacer el procesamiento en paralelo.

Si no puede hacer el procesamiento en paralelo, tal vez pueda usar dos o tres hilos. Dos para abrir archivos … y una cola para contener los objetos de archivo abierto que luego son consumidos por el procesamiento que realiza.

No permita que las colas crezcan sin límites: realmente solo necesita entre 4 y 8 entradas para mantener el procesamiento ocupado todo el tiempo. Si parece que la cola siempre está vacía … agregue más procesos abriendo archivos. De esta manera, su procesamiento nunca tiene que esperar por los datos.

Como muchos han notado, el problema aquí es la E / S. Es decir, su CPU está inactiva mientras la cabeza del disco busca la ubicación del nuevo archivo y espera que el disco gire suficientes veces para recoger el nuevo archivo (probablemente una vez si los archivos son realmente pequeños).

Formas de optimizar su rendimiento para esto:

1) Tienes toneladas de RAM. Si un Ramdisk de 3 GB contiene los 100,000 archivos, entonces eso es lo que recomendaría. Hay una herramienta gratuita llamada ImDisk que creará un RamDisk para usted. (Asumo Windows)

2) Mueva sus 100,000 archivos a otro lugar temporalmente, desfragmente su disco duro, luego mueva los 100,000 archivos de regreso. Esto los acercará más al disco físico y, por lo tanto, minimizará el tiempo de búsqueda. En un disco fragmentado, se dispersarán por todas partes. Esto también ayudaría con la solución que otros recomiendan, para concatenar los muchos archivos en uno. Tener un archivo grande no elimina las búsquedas a menos que se pueda almacenar de forma contigua en el disco.

3) Obtenga un SSD. Me doy cuenta de que esto podría no ser práctico. Pero reducirá su tiempo de búsqueda y lectura a 0, y todo lo que queda es la velocidad de transferencia SATA. Para toneladas de pequeños archivos, los SSD se destacan, por lo que los SSD hacen una gran diferencia en el arranque. el resto de su máquina es de alto rendimiento, por lo que es mejor que se dé cuenta de la potencia de la máquina si tiene un SSD de todos modos. Como se trata de una máquina de escritorio, puede agregar una SSD y no reemplazar la unidad principal si lo desea. Los precios han caído recientemente, por lo que se puede tener un SSD de 120GB por alrededor de $ 40.

La entrada de disco es lo que se ralentiza aquí.

Primero concatene los archivos en un archivo, o fragmentos. Experimente con los tamaños de los fragmentos, ya que debería haber un punto óptimo donde se pueda canalizar la lectura del archivo, de modo que el tiempo que lleva cargar un fragmento en la RAM sea suficiente para procesar otros archivos, por lo que todo el sistema siempre está ocupado.

SSD y caché de disco juegan un papel importante en E / S. También el sistema de archivos tiene un impacto, mira el tamaño en el disco de los archivos. Por ejemplo, un archivo de texto con solo 140char dentro pesa 1kb, al igual que un archivo de 800char, cuando tiene un disco duro formateado con un tamaño de cluster de 1kb.

Luego, con respecto al uso del procesador, el i7, al igual que todos los procesadores modernos, tiene la capacidad de ejecutar muchos hilos juntos. El procesador que enumeró tiene 4 MB de caché y 4 subprocesos, por lo que para usarlo completamente debe agregar algo de paralelización al programa.

Una gran ayuda sería reestructurar el programa para que haya un subproceso de cargador y un subproceso de cómputo, de modo que mientras se computa, se solicite el siguiente archivo, lo que permite al procesador canalizar las solicitudes.

En general, usar el procesador al 100% no es algo positivo, eso significa que perdió el control de la máquina (no hay tiempo para escuchar la entrada del usuario).

Probablemente limitado por E / S.

Entre las cosas que pueden ralentizarlo, está la gran cantidad de archivos para abrir / cerrar, y no poder mantener todos los archivos en la memoria por varias razones.

En Windows, el ajuste de la memoria caché de archivos se describe en Rendimiento y ajuste de la memoria caché de archivos

Si está en UNIX / Linux, debería obtener un almacenamiento en caché de archivos decente sin ajuste.

En ambas plataformas, 100,000 son bastantes archivos para abrir y cerrar. Podría sugerirle que comprima todos los archivos en un archivo grande y luego lo lea a través de zlib. Entonces, solo tendrá un archivo abierto, y probablemente estará en la caché del sistema de archivos.

Si todos los archivos encajaran en los 32G de memoria, podría intentar leerlo todo en la memoria, pero los muchos archivos se encuentran con el problema de abrir / cerrar.

Otra posibilidad es que no esté vinculado a E / S (particularmente), pero su programa se ejecuta en un solo subproceso y realmente no usa los seis núcleos en el i7 6850k. Obtener el 10% no es necesariamente malo, siendo el 75% de un núcleo. Para usar más CPU, necesitas usar más hilos. Eso significa abordar la concurrencia en los datos compartidos entre subprocesos, lo que puede ser un punto problemático.

Probablemente esté sujeto a transacciones de E / S. Los archivos pequeños pueden ser muy lentos de procesar. Dependiendo de su software, puede tener sentido canalizar los archivos en caché por cientos en lugar de uno a la vez. Además, una vez que se cargan los archivos, ¿cómo se procesan? ¿Por pedacitos? Bytes? ¿Palabras?

Hay muchos lugares donde puede estar disminuyendo la velocidad.