あなたのコンピュータが本来あるべきほど速くないという変な感じをしたことがありますか?以前はそのように感じていましたが、GNUParallelを見つけました。
GNU Parallelは、ジョブを並列で実行するためのシェルユーティリティです。複数の入力を解析できるため、データのセットに対して同時にスクリプトまたはコマンドを実行できます。 すべてを使用できます ついにあなたのCPU!
xargs
を使用したことがある場合 、Parallelの使用方法はすでに知っています。そうでない場合は、この記事で他の多くのユースケースとともに説明します。
GNUParallelのインストール
GNU Parallelは、LinuxまたはBSDコンピューターにプリインストールされていない場合があります。リポジトリまたはportsコレクションからインストールします。たとえば、Fedoraの場合:
$ sudo dnf install parallel
またはNetBSDの場合:
# pkg_add parallel
他のすべてが失敗した場合は、プロジェクトのホームページを参照してください。
シリアルからパラレルへ
その名前が示すように、Parallelの強みは、私たちの多くが今でも行っているように、ジョブを順番に実行するのではなく、並行して実行することです。
多くのオブジェクトに対して1つのコマンドを実行すると、本質的にキューが作成されます。いくつかのオブジェクトはコマンドで処理でき、他のすべてのオブジェクトはただ立って順番を待ちます。それは非効率的です。十分なデータがあれば、常にキューがありますが、キューを1つだけにするのではなく、小さなキューをたくさん持ってみませんか?
JPEGからPNGに変換したい画像でいっぱいのフォルダがあると想像してください。これを行うには多くの方法があります。 GIMPで各画像を手動で開き、新しい形式にエクスポートする方法があります。これは通常、考えられる最悪の方法です。時間と労力がかかるだけではありません。
このテーマのかなりきちんとしたバリエーションは、シェルベースのソリューションです:
$ convert 001.jpeg 001.png
$ convert 002.jpeg 002.png
$ convert 003.jpeg 003.png
... and so on ...
これは、最初に習得したときのすばらしいトリックであり、最初は大幅な改善です。 GUIや常時クリックは必要ありません。しかし、それでも労働集約的です。
さらに良い:
$ for i in *jpeg; do convert $i $i.png ; done
これにより、少なくとも、仕事が動き出し、より生産的なことを行えるようになります。問題は、それがまだシリアルプロセスであるということです。 1つの画像が変換され、キュー内の次の画像が変換のためにステップアップし、キューが空になるまで続きます。
パラレルの場合:
$ find . -name "*jpeg" | parallel -I% --max-args 1 convert % %.png
これは、find
という2つのコマンドの組み合わせです。 操作するオブジェクトを収集するコマンド、およびparallel
コマンド。オブジェクトを並べ替えて、すべてが必要に応じて処理されるようにします。
find . -name "*jpeg"
jpeg
で終わる現在のディレクトリ内のすべてのファイルを検索します 。parallel
GNUParallelを呼び出します。-
-I%
%
というプレースホルダーを作成します 、find
の代わりに Parallelに引き渡します。これを使用するのは、そうしないと、find
の結果ごとに新しいコマンドを手動で作成する必要があるためです。 、そしてそれはまさにあなたが避けようとしていることです。 -
--max-args 1
Parallelがキューから新しいオブジェクトを要求する速度を制限します。 Parallelが実行しているコマンドは1つのファイルしか必要としないため、レートを1に制限します。2つのファイルを必要とするより複雑なコマンド(cat 001.txt 002.txt > new.txt
など)を実行していましたか? )、レートを2に制限します。 -
convert % %.png
並列で実行するコマンドです。
このコマンドの結果は、find
です。 関連するすべてのファイルを収集し、それらをparallel
に渡します 、ジョブを起動し、すぐに次の行を要求します。 Parallelは、コンピューターに障害を与えることなく新しいジョブを安全に起動できる限り、これを継続します。古いジョブが完了すると、提供されたすべてのデータが処理されるまで、新しいジョブに置き換えられます。 10分前にかかっていたものは、Parallelでは5つか3つしかかからないかもしれません。
複数の入力
find
find
に精通している限り、コマンドはParallelへの優れたゲートウェイです。 およびxargs
(総称してGNU Find Utilities、またはfindutils
)。これは、多くのLinuxユーザーがすでに慣れ親しんでいる柔軟なインターフェースを提供し、初心者であれば非常に簡単に習得できます。
find
コマンドはかなり簡単です。find
を指定します 検索するディレクトリへのパスと、検索するファイル名の一部を指定します。ワイルドカード文字を使用して、ネットを広くキャストします。この例では、アスタリスクはすべてを示します 、だからfind
文字列searchterm
で終わるすべてのファイルを検索します :
$ find /path/to/directory -name "*searchterm"
デフォルトでは、find
1行に1つのアイテムを使用して、一度に1つのアイテムの検索結果を返します。
$ find ~/graphics -name "*jpg"
/home/seth/graphics/001.jpg
/home/seth/graphics/cat.jpg
/home/seth/graphics/penguin.jpg
/home/seth/graphics/IMG_0135.jpg
find
の結果をパイプするとき parallel
、各行の各項目は、parallel
というコマンドに対する1つの引数として扱われます。 仲裁中です。一方、1つのコマンドで複数の引数を処理する必要がある場合は、キュー内のデータをparallel
に渡す方法を分割できます。 。
これは単純で非現実的な例ですが、後でもっと便利なものに変えます。 GNU Parallelがインストールされている限り、この例に従うことができます。
4つのファイルがあると仮定します。それらを1行に1つずつリストして、自分が持っているものを正確に確認します。
$ echo ada > ada ; echo lovelace > lovelace
$ echo richard > richard ; echo stallman > stallman
$ ls -1
ada
lovelace
richard
stallman
2つのファイルを結合して、両方のファイルの内容を含む3番目のファイルにします。これには、Parallelが2つのファイルにアクセスできる必要があるため、-I%
この場合、変数は機能しません。
Parallelのデフォルトの動作は基本的に見えません:
$ ls -1 | parallel echo
ada
lovelace
richard
stallman
次に、ジョブごとに2つのオブジェクトを取得するようにParallelに指示します。
$ ls -1 | parallel --max-args=2 echo
ada lovelace
richard stallman
これで、行が結合されました。具体的には、 2 ls -1
の結果 一度にParallelに渡されます。これはこのタスクの適切な数の引数ですが、現時点では事実上1つの引数、「adalovelace」と「richardstallman」です。実際に必要なのは、ジョブごとに2つの異なる引数です。
幸い、その技術はParallel自体によって解析されます。 --max-args
を設定した場合 2
へ 、{1}
という2つの変数を取得します および{2}
、引数の最初と2番目の部分を表します:
$ ls -1 | parallel --max-args=2 cat {1} {2} ">" {1}_{2}.person
このコマンドでは、変数{1}
adaまたはrichard(どのジョブを見るかによって異なります)および{2}
lovelace
のいずれかです またはstallman
。ファイルの内容は、引用符で囲まれたリダイレクト記号でリダイレクトされます。 (引用符はBashからリダイレクトシンボルを取得して、Parallelがそれを使用できるようにします)そしてada_lovelace.person
と呼ばれる新しいファイルに配置されます およびrichard_stallman.person
。
$ ls -1
ada
ada_lovelace.person
lovelace
richard
richard_stallman.person
stallman
$ cat ada_*person
ada lovelace
$ cat ri*person
richard stallman
サイズが数百メガバイトのログファイルを1日中解析する場合、並列化されたテキスト解析がどのように役立つかがわかるかもしれません。それ以外の場合、これは主に実証的な演習です。
ただし、この種の処理は、テキストの解析だけでなく、非常に重要です。これが映画界の実例です。一緒に結合する必要があるビデオファイルとオーディオファイルのディレクトリを考えてみましょう。
$ ls -1
12_LS_establishing-manor.avi
12_wildsound.flac
14_butler-dialogue-mixed.flac
14_MS_butler.avi
...and so on...
同じ原則を使用して、ファイルを並列に結合するように簡単なコマンドを作成できます。 :
$ ls -1 | parallel --max-args=2 ffmpeg -i {1} -i {2} -vcodec copy -acodec copy {1}.mkv
ブルート。強制。
このような凝った入力と出力の解析は、すべての人の好みに合うものではありません。より直接的なアプローチを好む場合は、Parallelでコマンドをスローして、離れることができます。
まず、各行に1つのコマンドを含むテキストファイルを作成します。
$ cat jobs2run
bzip2 oldstuff.tar
oggenc music.flac
opusenc ambiance.wav
convert bigfile.tiff small.jpeg
ffmepg -i foo.avi -v:b 12000k foo.mp4
xsltproc --output build/tmp.fo style/dm.xsl src/tmp.xml
bzip2 archive.tar
次に、ファイルをParallelに渡します:
$ parallel --jobs 6 < jobs2run
これで、ファイル内のすべてのジョブが並列で実行されます。許可されているジョブよりも多くのジョブが存在する場合、すべてのジョブが実行されるまで、キューが形成され、Parallelによって維持されます。
はるかに
GNU Parallelは強力で柔軟なツールであり、この記事に収まらないほど多くのユースケースがあります。そのマニュアルページには、SSHを介したリモート実行から、並列コマンドへのBash関数の組み込みまで、これを使用して実行できる非常に優れた機能の例が記載されています。 YouTubeには広範なデモシリーズもあるので、GNUParallelチームから直接学ぶことができます。 GNU Parallelのリードメンテナは、Lulu.comから入手できるコマンドの公式ガイドもリリースしました。
GNU Parallelには、計算方法を変更する能力があります。変更しない場合は、少なくともコンピューターが計算に費やす時間を変更します。今日試してみてください!