【中級Linux】動画にAI効果を入れるテクニックと並列処理②【Imagemagick】
下記事のつづきです。
並列化すべき処理
今回の例における時間のかかる処理は、
AI処理(GFPGAN)
imagemagickによる画像のサイズ変換や合成
です。
AI処理(CUDA)自体は元々が「粒度」の高い並列処理である事と、GPUを最大限まで利用しているため、大容量メモリであったり、GPUが2つ以上ない限り並列化する利点は(あまり)ありません。
つまり、画像を合成するimagemagick処理部を並列化すると大きな利点を得られます。実際にimagemagickが処理する際にCPUはほとんど利用されていません。
並列化
前回のシェルスクリプトを並列化します。複雑な合成処理も行えるように、並列化する処理を関数にしておきます。
シェルスクリプトで並列化処理を行う時に注意すべき点は、
スレッドセーフにする事
スレッドセーフとは、プロセスが同時に動作した時に、変数やデータを壊さないようにする事です。今回の場合だと、たとえば一時ファイル名を固定の「tmp.png」にしてしまうと、別のプロセスが同時に同じ「tmp.png」にアクセスして壊してしまいます。
最近のAPIやライブラリでは、ライブラリ内でスレッドセーフ処理を行っているのであまり気にする事はありませんが、自分で処理を書く時は注意が必要です。
利用する変数や関数をexportする事
外部(別プロセス)からアクセスする時のおまじないです。
#!/bin/bash
set -eu
#作業ディレクトリに移動
cd ~/app/work
#並列処理数
num_cpus=8
#出力フォルダを作成
export out_dir=mov_out
if [ ! -e $out_dir ]; then
mkdir $out_dir
fi
#movフォルダの画像一枚ごとに処理
export folder1=mov #元動画
export folder2=results-gfpgan/restored_imgs #AI処理動画
#並列処理する関数
composite_image()
{
local file=$1
#ファイル名で分けてスレッドセーフにする
local f=`basename $file`
local tmp_f1="${f%.*}_f1.png"
local tmp_f2="${f%.*}_f2.png"
#画像サイズを統一する
convert -resize 512 $folder1/$f $tmp_f1
convert -resize 512 $folder2/$f $tmp_f2
#画像平均をとる
convert -average $tmp_f1 $tmp_f2 $out_dir/$f
#終了処理
rm -f $tmp_f1 $tmp_f2
}
export -f composite_image
#parallelコマンドで並列処理
find $folder1 -maxdepth 1 -type f -name "*.png" | parallel -j${num_cpus} composite_image
並列化前と並列化後を比べると
8スレッドに増やして8倍とはいきませんが、CPUを上手く利用できている事がわかります。
Linuxの並列化機能を利用する事で、imagemagickを利用した1枚ごとの単純な逐次処理でも現実的な時間で動画処理を行う事ができるようになります。
次回③へつづく。
以下関連記事の【PR】です。