¿Cómo iniciar grep multihilo en la terminal?

38

Tengo una carpeta que tiene más de 250 archivos de 2 GB cada uno. Necesito buscar una cadena / patrón en esos archivos y generar el resultado en un outputarchivo. Sé que puedo ejecutar el siguiente comando, ¡pero es demasiado lento!

grep mypattern * > output

Quiero acelerarlo Siendo un programador en Java, sé que los subprocesos múltiples se pueden usar para acelerar el proceso. Estoy atascado en cómo comenzar grepen el "modo de subprocesos múltiples" y escribir la salida en un solo outputarchivo.

Abhishek
fuente
Ver también unix.stackexchange.com/q/131535
Stéphane Chazelas
Y unix.stackexchange.com/q/85789
Stéphane Chazelas
1
Seguramente buscar en una gran colección de archivos es el ejemplo clásico de un problema que está vinculado a IO. Por lo tanto, usar múltiples hilos no ayudará.
Jonathan Hartley

Respuestas:

31

Hay dos soluciones fáciles para esto. Básicamente, usando xargso parallel.

Enfoque xargs:

Puede usar xargscon findlo siguiente:

find . -type f -print0  | xargs -0 -P number_of_processes grep mypattern > output

Donde lo reemplazará number_of_processespor el número máximo de procesos que desea iniciar. Sin embargo, esto no garantiza un rendimiento significativo en caso de que su rendimiento sea limitado de E / S. En ese caso, puede intentar iniciar más procesos para compensar el tiempo perdido esperando E / S.

Además, con la inclusión de find, puede especificar opciones más avanzadas en lugar de solo patrones de archivo, como el tiempo de modificación, etc.

Un posible problema con este enfoque, como lo explican los comentarios de Stéphane, si hay pocos archivos, xargspuede no iniciar suficientes procesos para ellos. Una solución será usar la -nopción para xargsespecificar cuántos argumentos debería tomar de la tubería a la vez. La configuración -n1obligará xargsa iniciar un nuevo proceso para cada archivo individual. Este podría ser un comportamiento deseado si los archivos son muy grandes (como en el caso de esta pregunta) y hay un número relativamente pequeño de archivos. Sin embargo, si los archivos mismos son pequeños, la sobrecarga de iniciar un nuevo proceso puede socavar la ventaja del paralelismo, en cuyo caso un -nvalor mayor será mejor. Por lo tanto, la -nopción podría ajustarse de acuerdo con el tamaño y el número del archivo.

Enfoque Paralelo:

Otra forma de hacerlo es usar la herramienta paralela Ole Tange GNU parallel(disponible aquí ). Esto ofrece un mayor control de grano fino sobre el paralelismo e incluso se puede distribuir en varios hosts (sería beneficioso si su directorio se comparte, por ejemplo). La sintaxis más simple usando paralelo será:

find . -type f | parallel -j+1 grep mypattern

donde la opción -j+1indica en paralelo que se inicie un proceso que exceda el número de núcleos en su máquina (Esto puede ser útil para tareas limitadas de E / S, incluso puede intentar aumentar su número).

Paralelo también tiene la ventaja xargsde retener realmente el orden de salida de cada proceso y generar una salida contigua. Por ejemplo, con xargs, si el proceso 1 genera una línea p1L1, digamos , el proceso 2 genera una línea p2L1, el proceso 1 genera otra línea p1L2, la salida será:

p1L1
p2L1
p1L2

mientras que con parallella salida debe ser:

p1L1
p1L2
p2L1

Esto suele ser más útil que la xargssalida.

Bichoy
fuente
1
Probablemente quieras usar -nen combinación con -P. De lo contrario, es xargsposible que no se generen varios procesos si hay dos pocos archivos.
Stéphane Chazelas
1
Bueno, -n1 comenzaría uno greppor archivo. A menos que los archivos sean muy grandes y haya muy pocos de ellos, es probable que desee aumentar eso un poco, ya que pasará su tiempo iniciando y deteniendo procesos grep en lugar de buscar archivos.
Stéphane Chazelas
9

Hay al menos dos formas de acelerar grep en cuanto a CPU:

  • Si está buscando una cadena fija en lugar de una expresión regular, especifique el -Findicador;

  • Si su patrón es solo ASCII, use una configuración regional de 8 bits en lugar de UTF-8, por ejemplo LC_ALL=C grep ....

Sin embargo, esto no ayudará si su disco duro es el cuello de botella; en ese caso, probablemente la paralelización tampoco ayudará.

egmont
fuente
1
Acabo de ver en man grep"La invocación directa como egrep o fgrep está en desuso, pero se proporciona para permitir que las aplicaciones históricas que dependen de ellos se ejecuten sin modificaciones". No estoy seguro que realmente importa, pero es lo mismo quegrep -F
iyrin
1
Además, cuando dices "en lugar de un patrón", ¿te refieres a una expresión regular?
iyrin
La búsqueda "ASCII-only" usa masivamente menos CPU. Pero debe leer las advertencias mencionadas en los comentarios en stackoverflow.com/a/11777835/198219
famzah el
3

Si el problema no está vinculado a E / S, puede usar una herramienta que esté optimizada para el procesamiento multinúcleo.

Es posible que desee echar un vistazo a sift ( http://sift-tool.org , descargo de responsabilidad: soy el autor de esta herramienta) o el buscador de plata ( https://github.com/ggreer/the_silver_searcher ).

el buscador plateado tiene un límite de tamaño de archivo de 2 GB si usa un patrón de expresiones regulares y no una búsqueda de cadena de espinillas.

svent
fuente
¿Seguramente buscar un montón de archivos es un ejemplo clásico de un problema que está vinculado a IO?
Jonathan Hartley