これに近い答えを見つけましたが、私の場合はどのように使用するのか理解できません(私は初めてBashに触れました)...それで、大量の画像シーケンス(100,000を超えるファイル)を含むフォルダを処理しようとしています。 Imagemagickを使用してGNU Parallelを使用すると、作業速度が向上することを願っています。
以下は私が使用するコードです(メモリ不足を防ぐために一度に100フレームを処理します)。
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
これをどのように「並列化」しますか?私が見つけたほとんどのソリューションはループではなくパイプを使用していますが、これはパラメータリストが長すぎてスクリプトがクラッシュする問題を引き起こしました。
私が望むのは、parallel
負荷を分割することです。たとえば、最初の100フレームをコア1に提供し、フレーム100〜199をコア2に提供する式です。
答え1
注文する
あなたのプログラム例は、構成する配列の順序に興味がないようですが、あなた*.png
のallframes
意見では順序が重要であると信じていました。
私が望むのは、負荷を並列に分割することです。たとえば、最初の100フレームをコア1に提供し、フレーム100〜199をコア2に提供するなどの作業を実行します。
吹く
そこで、まず以下のようにスクリプトを変更して、ファイルが番号allframes
順に保存されるように配列の構造を変更しました。
allframes=($(printf "%s\n" *.png | sort -V | tr '\n' ' '))
これは、以下を使用してさらに簡素化できますsort -zV
。
allframes=($(printf "%s\0" *.png | sort -zV | tr '\0' ' '))
これはconvert ...
ビルドコマンドに影響を与えるため、次のようになります。
$ convert "0.png 1.png 2.png 3.png 4.png 5.png 6.png 7.png 8.png 9.png \
10.png 11.png 12.png 13.png 14.png 15.png 16.png 17.png 18.png \
19.png 20.png 21.png 22.png 23.png 24.png 25.png 26.png 27.png \
28.png 29.png 30.png 31.png 32.png 33.png 34.png 35.png 36.png \
37.png 38.png 39.png 40.png 41.png 42.png 43.png 44.png 45.png \
46.png 47.png 48.png 49.png 50.png 51.png 52.png 53.png 54.png \
55.png 56.png 57.png 58.png 59.png 60.png 61.png 62.png 63.png \
64.png 65.png 66.png 67.png 68.png 69.png 70.png 71.png 72.png \
73.png 74.png 75.png 76.png 77.png 78.png 79.png 80.png 81.png \
82.png 83.png 84.png 85.png 86.png 87.png 88.png 89.png 90.png \
91.png 92.png 93.png 94.png 95.png 96.png 97.png 98.png 99.png" \
-evaluate-sequence "mean" -channel RGB -normalize ../out2/0.png
類似点
parallel
eschwartzの例に基づいて、次の例を構成しました。
$ printf '%s\n' *.png | sort -V | parallel -n100 --dryrun convert {} \
-evaluate-sequence 'mean' -channel RGB -normalize ../out2/{1}
もう一度使用する方が簡単ですsort -zV
。
$ printf '%s\0' *.png | sort -zV | parallel -0 -n100 --dryrun "convert {} \
-evaluate-sequence 'mean' -channel RGB -normalize ../out2/{1}
メモ:parallel
スタート操作として、上にエコー「…」があります。これにより、何が起こっているのかを視覚化するのに役立ちます。
$ convert 0.png 1.png 2.png 3.png 4.png 5.png 6.png 7.png 8.png 9.png 10.png \
11.png 12.png 13.png 14.png 15.png 16.png 17.png 18.png 19.png \
20.png 21.png 22.png 23.png 24.png 25.png 26.png 27.png 28.png \
29.png 30.png 31.png 32.png 33.png 34.png 35.png 36.png 37.png \
38.png 39.png 40.png 41.png 42.png 43.png 44.png 45.png 46.png \
47.png 48.png 49.png 50.png 51.png 52.png 53.png 54.png 55.png \
56.png 57.png 58.png 59.png 60.png 61.png 62.png 63.png 64.png \
65.png 66.png 67.png 68.png 69.png 70.png 71.png 72.png 73.png \
74.png 75.png 76.png 77.png 78.png 79.png 80.png 81.png 82.png \
83.png 84.png 85.png 86.png 87.png 88.png 89.png 90.png 91.png \
92.png 93.png 94.png 95.png 96.png 97.png 98.png 99.png \
-evaluate-sequence mean -channel RGB -normalize ../out2/0.png
この出力がうまくいったら、スイッチをに移して--dryrun
もう一度parallel
実行してください。
$ printf '%s\0' *.png | sort -zV | parallel -0 -n100 convert {} \
-evaluate-sequence 'mean' -channel RGB -normalize
引用する
答え2
printf '%s\0' *.png
正しい解決策は、コマンドライン引数の長さのARG_MAX制限に影響されないシェル組み込みコマンドを使用してファイル名を印刷し、パイプを介してそのファイル名をparallel --null
読み取り、必要に応じてジョブをバッチ処理することです。
parallel
以下の機能の一部を使用しています。
--null
奇妙なファイル名による奇妙な問題を回避するには、ファイル名をnull文字に賢明に分割する必要があります。-n 100
xargsと同様に、各呼び出しは100個のファイルを処理します。{}
次の100個のファイル名が含まれています。../out2/{1}
最初の項目のみを含める
したがって、これは次のようになります。
calcmethod1=mean
printf '%s\0' *.png | parallel --null -n 100 convert {} -evaluate-sequence $calcmethod1 -channel RGB -normalize {} ../out2/{1}
なぜパイプが機能しないと思いますか?パイプラインはうまく機能しますが、外部分岐コマンドのみが機能します。いいえパイプで読んでいる間、問題パラメータ長。パイプは実際にparallel
。
答え3
convert
各プロセスは独自のサブシェルで実行できます。
#!/bin/bash
for (( i=1; i<=1000; i++ )) do
(
command --options ) &
disown
done
exit 0
どのように機能するかを確認するには、次のスクリプトを試してください。
#!/bin/bash
echo "Hi!"
for (( i=1; i<=1000; i++ )) do
(
sleep 30
echo "Bye, "$i"!" ) &
disown
done
exit 0
スクリプト名を指定par.sh
したら、プロセスを確認してください。
ps aux | grep par.sh
各サブシェルには別々のPIDがあるため、デフォルトのLinux CPUロードバランサはプロセスをCPUコアに均等に分散する必要があると想定できます。とにかく同様のものはcpuset
常に利用可能です。