Tengo tres tipos de datos que están en diferentes formatos; Para cada tipo de datos, hay un script de Python que lo transforma en un único formato unificado.
Este script de Python es lento y está vinculado a la CPU (a un solo núcleo en una máquina multinúcleo), por lo que quiero ejecutar tres instancias del mismo, una para cada tipo de datos, y combinar su salida para pasarlo sort. Básicamente, equivalente a esto:
{ ./handle_1.py; ./handle_2.py; ./handle_3.py } | sort -n
Pero con los tres scripts ejecutándose en paralelo.
Encontré esta pregunta en la que GNU splitse estaba utilizando para hacer un round-robin de una secuencia estándar entre n instancias de un script que maneja la secuencia.
Desde la página man dividida:
-n, --number=CHUNKS
          generate CHUNKS output files.  See below
CHUNKS  may be:
 N       split into N files based on size of input
 K/N     output Kth of N to stdout
 l/N     split into N files without splitting lines
 l/K/N   output Kth of N to stdout without splitting lines
 r/N     like 'l'  but  use  round  robin  distributio
Entonces el r/Ncomando implica " sin dividir líneas ".
En base a esto, parece que la siguiente solución debería ser factible:
split -n r/3 -u --filter="./choose_script" << EOF
> 1
> 2
> 3
> EOF
Donde choose_scripthace esto:
#!/bin/bash
{ read x; ./handle_$x.py; }
Desafortunadamente, veo algunas líneas entremezcladas, y muchas líneas nuevas que no deberían estar allí.
Por ejemplo, si reemplazo mis scripts de Python con algunos scripts de bash simples que hacen esto:
#!/bin/bash
# ./handle_1.sh
while true; echo "1-$RANDOM"; done;
.
#!/bin/bash
# ./handle_2.sh
while true; echo "2-$RANDOM"; done;
.
#!/bin/bash
# ./handle_3.sh
while true; echo "3-$RANDOM"; done;
Veo esta salida:
1-8394
2-11238
2-22757
1-723
2-6669
3-3690
2-892
2-312511-24152
2-9317
3-5981
Esto es molesto: según el extracto de la página de manual que pegué anteriormente, debería mantener la integridad de la línea.
Obviamente, funciona si elimino el -uargumento, pero luego está almacenado en el búfer y me quedaré sin memoria, ya que amortigua la salida de todos menos uno de los scripts.
Si alguien tiene alguna idea aquí, sería muy apreciado. Estoy fuera de mi profundidad aquí.

coprocbuiltin en bash, aunque realmente no veo cómo se aplica.job1.py > file1 & job2.py > file 2 & job3.py > file3 ; wait ; sort -n file1 file2 file3?Respuestas:
Intente usar la opción -u de GNU paralela.
Esto los ejecuta en paralelo, sin amortiguar la totalidad de ningún proceso.
fuente
XdeIXdecir-Ique X será la bandera para reemplazar, o está aplicando la-Xbandera, que aparentemente también tiene un significado relevante?parallel -u -X ./handle_{}.sh ::: "1" "2" "3"y, desafortunadamente, todavía veo algunos cambios de salida.parallel -u ./handle_{}.sh, pero prefiero cambiarlo, ya que los corchetes también tienen el significado de unir comandos (como en su pregunta).Tratar:
Si
handle_1.pytoma un nombre de archivo:No desea que la salida se mezcle, así que no use -u.
Si desea mantener el orden (por lo que toda la salida de handle_1 es anterior a handle_2 y, por lo tanto, puede evitar la clasificación):
Si aún desea ordenarlo, puede paralelizar el orden y utilizar
sort -m:Establezca $ TMPDIR en un directorio que sea lo suficientemente grande como para contener la salida.
fuente
Tal vez me estoy perdiendo algo, pero no puedes simplemente hacer:
Si desea que las líneas de cada proceso no se intercalen, lo más fácil es asegurarse de que el proceso mismo las escriba por completo y posiblemente deshabilite el almacenamiento en búfer de salida, ya
writeque se garantiza que los valores atómicos de una tubería sean atómicos siempre que no sean más grandes quePIPE_BUF. Por ejemplo, usted podría asegurarse de que hace búfer de salida a la utilizaciónstdioy la llamadafflusho lo que es el equivalente enpythondespués de una o unas pocas líneas se han escrito.Si no puede modificar los scripts de Python, puede hacer lo siguiente:
(con GNU grep) o:
(Consulte las notas en los comentarios a continuación si la salida de los comandos no es texto)
Y hacer:
Otra opción para evitar esos 3
lbprocesos es tener tres canales para un comando que useselect/pollpara ver de dónde proviene alguna salida y alimentarla ensortlínea, pero requiere un poco de programación.fuente
waitallí, creo.sort -npermanecerá hasta que todos los programas que tienen un fd abierto hayan salido.La respuesta de Flowbok fue la solución correcta. Curiosamente, la salida de GNU
parallelse destruye si se envía directamente a un archivo, pero no si va a un tty.Afortunadamente,
script -cestá disponible para imitar un tty.Todavía quedan los tres guiones:
.
.
Luego hay un archivo que encapsula la llamada al paralelo:
Y luego lo llamo así:
Las líneas en la salida se mezclan línea por línea entre la salida de los diferentes scripts, pero no se mutilan ni se intercalan en una línea determinada.
Comportamiento extraño de
parallel: puedo presentar un informe de error.fuente