Maneira eficiente de usar todos os núcleos no script bash ou zsh

6

Se eu quiser processar um grande número de arquivos com o comando "do_something", que pode usar apenas um núcleo, qual é a melhor maneira de usar todos os núcleos disponíveis, presumindo que cada arquivo possa ser processado independentemente?

Neste momento, faço algo assim:

#!/bin/zsh
TASK_LIMIT=8
TASKS=0
for i in *(.)
{
  do_something "$i"&
  TASKS=$(($TASKS+1))
  if [[ $TASKS -ge $TASK_LIMIT ]]; then
    wait; TASKS=0; fi
}
wait

Obviamente, isso não é eficiente porque depois de atingir $ TASK_LIMIT, ele espera quando todos os "do_something" terminam. Por exemplo, no meu script real eu uso cerca de 500% do meu processador de 8 núcleos em vez de > 700%.

A execução sem $ TASK_LIMIT não é uma opção porque "do_something" pode consumir muita memória.

Idealmente, o script deve tentar manter o número de tarefas paralelas em $ TASK_LIMIT: por exemplo, se a tarefa 1 de 8 tiver terminado e houver pelo menos mais um arquivo para processar, o script deverá executar próximo "do_something" em vez de aguardar restantes 7 tarefas para terminar. Existe uma maneira de conseguir isso em zsh ou bash?

    
por Lissanro Rahyen 26.10.2012 / 17:19

2 respostas

6

Eu sugiro strongmente que você dê uma olhada no paralelo GNU . Ele faz exatamente o que você quer e não depende de qualquer shell particular.

    
por 26.10.2012 / 19:09
0

Lembre-se de quantos processos você iniciou. Quando um processo termina, diminua a contagem. Quando a contagem for menor que o máximo, inicie um novo processo.

O único problema é como sinalizar o final de um processo. Você pode, por exemplo crie um arquivo emty de um determinado nome em / tmp (composto por $$ e $ BASHPID).

    
por 26.10.2012 / 17:38