Encontrei respostas próximas a isso, mas não consigo entender como usá-las no meu caso (sou bastante novo no Bash) ... com Imagemagick e gostaria de usar GNU Parallel para acelerar as coisas.
Este é o código que eu uso (processando 100 quadros por vez para evitar ficar sem memória ram):
calcmethod1=mean;
allframes=(*.png)
cd out1
for (( i=0; i < "${#allframes[@]}" ; i+=100 )); do
convert "${allframes[@]:i:100}" -evaluate-sequence "$calcmethod1" \
-channel RGB -normalize ../out2/"${allframes[i]}"
done
como eu 'paralelizar' isso? A maioria das soluções que encontrei funciona sem usar um loop, mas uma tubulação - mas, ao fazer isso, me deparei com o problema de que meu script quebraria por causa da minha lista de argumentos ficar muito longa ...
Eu acho que o que eu gostaria de fazer é parallel
dividir a carga como entregar os primeiros 100 quadros ao núcleo 1, quadros 100-199 ao núcleo 2 etc.?
A solução correta é imprimir os nomes dos arquivos usando um shell embutido como
printf '%s\0' *.png
o qual não é vulnerável à limitação ARG_MAX no comprimento do argumento da linha de comando e, em seguida, canalizá-lo para oparallel --null
qual lerá esses nomes de arquivos e agrupará os trabalhos da maneira que desejar.Algumas funcionalidades
parallel
que iremos utilizar:--null
é necessário para dividir nomes de arquivos de forma sensata em caracteres nulos para evitar problemas estranhos com nomes de arquivos estranhos-n 100
irá, assim como xargs, lidar com 100 arquivos para cada chamada{}
contém esses 100 nomes de arquivos../out2/{1}
contém apenas o primeiroEntão, isso se tornaria:
Por que você acha que a tubulação não funcionaria? A tubulação funciona bem, são apenas comandos bifurcados externamente que não são lidos de um tubo, que têm problemas com o comprimento do argumento . A tubulação é de fato todo o propósito do
parallel
.Ordem
Seu programa de exemplo não parecia se importar com a ordem do
*.png
arrayallframes
que você estava construindo, mas seus comentários me levaram a acreditar que a ordem importaria.festança
Portanto, eu começaria com uma modificação no seu script assim, alterando a construção do
allframes
array para que os arquivos sejam armazenados em ordem numérica.Isso pode ser simplificado ainda mais usando
sort -zV
:Isso tem o efeito de construir seus
convert ...
comandos para que fiquem assim agora:Paralelos
Com base no exemplo de eschwartz, montei um
parallel
exemplo da seguinte forma:novamente, mais simplesmente usando
sort -zV
:NOTA: O acima tem um eco "..." como a
parallel
ação para iniciar. Fazer desta forma ajuda a visualizar o que está acontecendo:Se você estiver satisfeito com esta saída, simplesmente remova a
--dryrun
opção paraparallel
e execute-a novamente.Referências
É possível executar cada
convert
processo em seu próprio subshell:Para ver como funciona, tente este script:
Atribua ao nome do script
par.sh
e verifique os processos posteriormente:Podemos supor que o balanceador de carga de CPU Linux nativo deve distribuir os processos entre os núcleos de CPU uniformemente, pois cada subshell possui um pid separado. De qualquer forma, algo como
cpuset
está sempre disponível para ser usado.