Considere o seguinte cenário. Eu tenho dois programas A e B. O programa A produz saídas padrão de linhas de strings enquanto o programa B processa linhas de stdin. A maneira de usar esses dois programas é obviamente:
foo @ bar: ~ $ A | B
Agora notei que isso consome apenas um núcleo; por isso estou me perguntando:
Os programas A e B estão compartilhando os mesmos recursos computacionais? Em caso afirmativo, existe uma maneira de executar A e B simultaneamente?
Outra coisa que notei é que A roda muito mais rápido que B, portanto, estou pensando se poderia, de alguma forma, executar mais programas B e deixá-los processar as linhas que A produz em paralelo.
Ou seja, A produziria suas linhas e haveria N instâncias dos programas B que liam essas linhas (quem as lê primeiro) as processam e as produzem no stdout.
Então, minha pergunta final é:
Existe uma maneira de canalizar a saída para A entre vários processos B sem precisar cuidar das condições da corrida e de outras inconsistências que possam surgir?
fonte
A | B | C
seja paralelo como em processos separados, devido à natureza dos tubos (B precisa aguardar a saída de A, C deve aguardar a saída de B), ainda pode ser linear em alguns casos. Depende inteiramente do tipo de produção que eles produzem. Não há muitos casos em que executar múltiplosB
ajudaria muito, é perfeitamente possível que o exemplo wc paralelo seja mais lento que o normal,wc
pois a divisão pode levar mais recursos do que contar linhas normalmente. Use com cuidado.Respostas:
Um problema
split --filter
é que a saída pode ser misturada, de modo que você obtém meia linha do processo 1, seguida por meia linha do processo 2.O GNU Parallel garante que não haverá confusão.
Então, suponha que você queira fazer:
Mas esse B é terrivelmente lento e, portanto, você deseja paralelizar isso. Então você pode fazer:
Por padrão, o GNU Parallel divide-se em \ n e um tamanho de bloco de 1 MB. Isso pode ser ajustado com --recend e --block.
Você pode encontrar mais informações sobre o GNU Parallel em: http://www.gnu.org/s/parallel/
Você pode instalar o GNU Parallel em apenas 10 segundos com:
Assista ao vídeo de introdução em http://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
fonte
--block-size
dependerá da quantidade de RAM e da rapidez com que você pode iniciar um novoB
. Na sua situação, eu usaria--block 100M
e veria como isso funcionava.sh
- é ótimo. O problema está em passar para sh: baixar e executar código executável de um site . Lembre-se, talvez eu esteja sendo paranóico demais, já que alguém poderia objetar que um RPM ou DEB personalizado é basicamente a mesma coisa, e até postar o código em uma página a ser copiada e colada resultaria em pessoas fazendo isso cegamente de qualquer forma.Quando você escreve
A | B
, os dois processos já são executados em paralelo. Se você vê-los usando apenas um núcleo, provavelmente é por causa das configurações de afinidade da CPU (talvez haja alguma ferramenta para gerar um processo com afinidade diferente) ou porque um processo não é suficiente para armazenar um núcleo inteiro e o sistema " prefere "não espalhar a computação.Para executar vários B's com um A, você precisa de uma ferramenta como
split
a--filter
opção:No entanto, isso pode atrapalhar a ordem das linhas na saída, porque os trabalhos B não serão executados todos na mesma velocidade. Se este for um problema, pode ser necessário redirecionar a saída i para um arquivo intermediário e costurá-las no final usando
cat
. Por sua vez, isso pode exigir um espaço considerável em disco.Existem outras opções (por exemplo, você pode limitar cada instância de B a uma única saída com buffer de linha, esperar até que toda uma "rodada" de B seja concluída, executar o equivalente a uma redução no mapa de
split
s e a saída temporária em conjunto), com níveis variados de eficiência. A opção 'round' descrita acima, por exemplo, aguardará a conclusão da instância mais lenta de B , portanto, dependerá muito do buffer disponível para B; pode ajudar, ou não, dependendo de quais são as operações.cat
[m]buffer
Exemplos
Gere os primeiros 1000 números e conte as linhas em paralelo:
Se "marcássemos" as linhas, veríamos que cada primeira linha é enviada para o processo 1, cada quinta linha para o processo 5 e assim por diante. Além disso, no tempo necessário
split
para gerar o segundo processo, o primeiro já é um bom caminho para sua cota:Ao executar numa máquina de dois núcleos,
seq
,split
e oswc
processos compartilham os núcleos; mas olhando mais de perto, o sistema deixa os dois primeiros processos na CPU0 e divide a CPU1 entre os processos de trabalho:Observe especialmente que
split
está consumindo uma quantidade considerável de CPU. Isso diminuirá proporcionalmente às necessidades de A; isto é, se A for um processo mais pesado queseq
, a sobrecarga relativasplit
diminuirá. Mas se A é um processo muito leve e B é bastante rápido (para que você não precise de mais do que 2-3 B's para acompanhar A), paralelizar comsplit
(ou tubos em geral) pode não valer a pena.fonte
split
--filter
opção está faltando? No meu Ubuntu 12.04-LTS ("wheezy / sid"), ele está lá, e meus exemplos funcionam. Você poderia ter instalado um diferentesplit
do GNU coreutils?