Cuando escribe A | B
, ambos procesos ya se ejecutan en paralelo. Si ve que usan solo un núcleo, probablemente se deba a la configuración de afinidad de la CPU (quizás haya alguna herramienta para generar un proceso con diferente afinidad) o porque un proceso no es suficiente para mantener un núcleo completo, y el sistema " prefiere "no extender la informática.
Para ejecutar varias B con una A, necesita una herramienta como split
con la --filter
opción:
A | split [OPTIONS] --filter="B"
Sin embargo, esto puede estropear el orden de las líneas en la salida, porque los trabajos B no se ejecutarán a la misma velocidad. Si esto es un problema, es posible que deba redirigir la salida B i-th a un archivo intermedio y unirlas al final usando cat
. Esto, a su vez, puede requerir un considerable espacio en disco.
Existen otras opciones (por ejemplo, se podría limitar a cada instancia de B a una sola línea de salida de búfer, espere hasta que su conjunto "redondo" de B ha finalizado, ejecute el equivalente de una a reducir a split
's mapa , y cat
la salida temporal juntos), con diferentes niveles de eficiencia. La opción 'redonda' que se acaba de describir, por ejemplo, esperará a que finalice la instancia más lenta de B , por lo que dependerá en gran medida del almacenamiento en búfer disponible para B; [m]buffer
puede ayudar, o puede que no, dependiendo de cuáles sean las operaciones.
Ejemplos
Genere los primeros 1000 números y cuente las líneas en paralelo:
seq 1 1000 | split -n r/10 -u --filter="wc -l"
100
100
100
100
100
100
100
100
100
100
Si tuviéramos que "marcar" las líneas, veríamos que cada primera línea se envía al proceso # 1, cada quinta línea al proceso # 5 y así sucesivamente. Además, en el tiempo que lleva split
generar el segundo proceso, el primero ya es un buen camino hacia su cuota:
seq 1 1000 | split -n r/10 -u --filter="sed -e 's/^/$RANDOM - /g'" | head -n 10
19190 - 1
19190 - 11
19190 - 21
19190 - 31
19190 - 41
19190 - 51
19190 - 61
19190 - 71
19190 - 81
Cuando se ejecuta en una máquina de 2 núcleos seq
, split
y los wc
procesos comparten los núcleos; pero mirando más de cerca, el sistema deja los dos primeros procesos en CPU0 y divide la CPU1 entre los procesos de trabajo:
%Cpu0 : 47.2 us, 13.7 sy, 0.0 ni, 38.1 id, 1.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 15.8 us, 82.9 sy, 0.0 ni, 1.0 id, 0.0 wa, 0.3 hi, 0.0 si, 0.0 st
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
5314 lserni 20 0 4516 568 476 R 23.9 0.0 0:03.30 seq
5315 lserni 20 0 4580 720 608 R 52.5 0.0 0:07.32 split
5317 lserni 20 0 4520 576 484 S 13.3 0.0 0:01.86 wc
5318 lserni 20 0 4520 572 484 S 14.0 0.0 0:01.88 wc
5319 lserni 20 0 4520 576 484 S 13.6 0.0 0:01.88 wc
5320 lserni 20 0 4520 576 484 S 13.3 0.0 0:01.85 wc
5321 lserni 20 0 4520 572 484 S 13.3 0.0 0:01.84 wc
5322 lserni 20 0 4520 576 484 S 13.3 0.0 0:01.86 wc
5323 lserni 20 0 4520 576 484 S 13.3 0.0 0:01.86 wc
5324 lserni 20 0 4520 576 484 S 13.3 0.0 0:01.87 wc
Observe especialmente que se split
está comiendo una cantidad considerable de CPU. Esto disminuirá en proporción a las necesidades de A; es decir, si A es un proceso más pesado que seq
, la sobrecarga relativa de split
disminuirá. Pero si A es un proceso muy liviano y B es bastante rápido (por lo que no necesita más de 2-3 B para mantenerse junto con A), entonces la paralelización con split
(o tuberías en general) bien podría no valer la pena.
A | B | C
es paralelo como en procesos separados, debido a la naturaleza de las tuberías (B tiene que esperar la salida de A, C tiene que esperar la salida de B) aún puede ser lineal en algunos casos. Depende completamente de qué tipo de salida producen. No hay muchos casos en los que la ejecución de múltiplesB
ayude mucho, es muy posible que el ejemplo de wc paralelo sea más lento que el normal,wc
ya que dividir puede requerir más recursos que contar líneas normalmente. Usar con cuidado.