Eu tenho tentado paralelizar o script a seguir, especificamente cada uma das três instâncias de loop FOR, usando o GNU Parallel, mas não consegui. Os 4 comandos contidos no loop FOR são executados em série, cada loop levando cerca de 10 minutos.
#!/bin/bash
kar='KAR5'
runList='run2 run3 run4'
mkdir normFunc
for run in $runList
do
fsl5.0-flirt -in $kar"deformed.nii.gz" -ref normtemp.nii.gz -omat $run".norm1.mat" -bins 256 -cost corratio -searchrx -90 90 -searchry -90 90 -searchrz -90 90 -dof 12
fsl5.0-flirt -in $run".poststats.nii.gz" -ref $kar"deformed.nii.gz" -omat $run".norm2.mat" -bins 256 -cost corratio -searchrx -90 90 -searchry -90 90 -searchrz -90 90 -dof 12
fsl5.0-convert_xfm -concat $run".norm1.mat" -omat $run".norm.mat" $run".norm2.mat"
fsl5.0-flirt -in $run".poststats.nii.gz" -ref normtemp.nii.gz -out $PWD/normFunc/$run".norm.nii.gz" -applyxfm -init $run".norm.mat" -interp trilinear
rm -f *.mat
done
shell-script
gnu-parallel
Ravnoor S Gill
fonte
fonte
wait
comando no final para que o script mestre não saia até que todos os trabalhos em segundo plano o façam.nice
, mas então eu não sei se alguma vez terminar ..Tarefa de amostra
Execuções sequenciais
Execuções paralelas
Execuções paralelas em lotes do processo N
Também é possível usar FIFOs como semáforos e usá-los para garantir que novos processos sejam gerados o mais rápido possível e que não mais que N processos sejam executados ao mesmo tempo. Mas isso requer mais código.
N processos com um semáforo baseado em FIFO:
fonte
wait
ele basicamente permite que todos os processos sejam executados, até atingir onth
processo, e aguarda que todos os outros terminem de executar, certo?i
for zero, ligue para aguardar. Incrementoi
após o teste zero.wait
w / no arg aguarda todas as crianças. Isso torna um pouco inútil. A abordagem baseada em tubo de semáforo dá-lhe concorrência mais fluente (Eu tenho usado isso em um sistema de compilação com base shell personalizado junto com-nt
/-ot
cheques com sucesso por um tempo agora)mkfifo pipe-$$
comando precisa de acesso de gravação apropriado ao diretório atual. Portanto, prefiro especificar o caminho completo, como/tmp/pipe-$$
provavelmente o acesso de gravação disponível para o usuário atual, em vez de depender do diretório atual. Sim, substitua todas as 3 ocorrências depipe-$$
.Se ele realmente funciona depende de seus comandos; Eu não estou familiarizado com eles. O
rm *.mat
parece um pouco propenso a conflitos se ele é executado em paralelo ...fonte
rm *.mat
para algo comorm $run".mat"
fazê-lo funcionar sem que um processo interfira no outro. Obrigado .wait
, que eu esqueci.Isso usará semáforos, paralelizando tantas iterações quanto o número de núcleos disponíveis (-j +0 significa que você paralelizará N + 0 trabalhos , onde N é o número de núcleos disponíveis ).
o sem --wait diz para esperar até que todas as iterações no loop for tenham terminado a execução antes de executar as sucessivas linhas de código.
Nota: você precisará "paralelamente" do projeto paralelo GNU (sudo apt-get install parallel).
fonte
Uma maneira realmente fácil que eu costumo usar:
Isso executará o comando, passando em cada linha do arquivo "args", paralelamente, executando no máximo $ NUM_PARALLEL ao mesmo tempo.
Você também pode procurar na opção -I xargs, se precisar substituir os argumentos de entrada em locais diferentes.
fonte
Parece que os trabalhos fsl dependem um do outro, portanto, os 4 trabalhos não podem ser executados em paralelo. As execuções, no entanto, podem ser executadas em paralelo.
Faça uma função bash executando uma única execução e execute essa função em paralelo:
Para saber mais, assista aos vídeos de introdução: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1 e passe uma hora percorrendo o tutorial http://www.gnu.org/software/parallel/parallel_tutorial.html Seu comando linha vai te amar por isso.
fonte
export SHELL=/bin/bash
antes de executar em paralelo. Caso contrário, você receberá um erro como:Unknown command 'myfunc arg'
Execução paralela no máximo processo N simultâneo
fonte
Eu realmente gosto da resposta do @lev, pois fornece controle sobre o número máximo de processos de uma maneira muito simples. No entanto, conforme descrito no manual , o sem não funciona com colchetes.
Faz o trabalho.
fonte
No meu caso, como não posso usar o semáforo (estou no git-bash no Windows), criei uma maneira genérica de dividir a tarefa entre os N trabalhadores, antes que eles comecem.
Funciona bem se as tarefas levarem aproximadamente a mesma quantidade de tempo. A desvantagem é que, se um dos trabalhadores demorar muito para fazer sua parte do trabalho, os outros que já terminaram não ajudarão.
Divisão do trabalho entre N trabalhadores (1 por núcleo)
fonte
Eu tive problemas com
@PSkocik
a solução. Meu sistema não possui o GNU Parallel disponível como pacote esem
lançou uma exceção quando eu o criei e o executei manualmente. Tentei também o exemplo de semáforo FIFO, que também gerou alguns outros erros em relação à comunicação.@eyeApps
xargs sugerido, mas eu não sabia como fazê-lo funcionar com meu caso de uso complexo (exemplos seriam bem-vindos).Aqui está minha solução para trabalhos paralelos que processam até
N
trabalhos por vez, conforme configurado por_jobs_set_max_parallel
:_lib_jobs.sh:
Exemplo de uso:
fonte