一般的なLinuxディストリビューションでは、、、、rm
などmv
のユーティリティはその引数と並列に実行されますか?ls
grep
wc
つまり、grep
32スレッドCPUで大容量ファイルを処理すると、デュアルコアCPUよりも高速に実行されますか?
答え1
ユーティリティがライブラリに関連付けられていることを確認すると、最初の印象を知ることができますpthread
。オペレーティングシステムスレッドを使用する動的にリンクされたプログラムはpthreadライブラリを使用する必要があります。
ldd /bin/grep | grep -F libpthread.so
Ubuntuを例に挙げてみましょう。
for x in $(dpkg -L coreutils grep findutils util-linux | grep /bin/); do if ldd $x | grep -q -F libpthread.so; then echo $x; fi; done
ただし、プログラム自体がpthreadに関連付けられているライブラリに関連付けられているため、多数の誤検出が発生します。たとえば、/bin/mkdir
私のシステムでは、それ自体がpthreadに関連付けられているPCRE(理由はわかりません...)に関連付けられています。しかし、mkdir
どのような方法で並列化されていない。
実際には、実行可能ファイルが含まれていることを確認すると、libpthread
より信頼できる結果が得られます。並列動作がライブラリに完全に含まれている実行可能ファイルが欠落している可能性がありますが、デフォルトのユーティリティは通常そのように設計されていません。
dpkg -L coreutils grep findutils util-linux | grep /bin/ | xargs grep pthread
Binary file /usr/bin/timeout matches
Binary file /usr/bin/sort matches
したがって、実際に並列化できる唯一のツールはですsort
。 (timeout
librtに接続されているのでlibpthreadにのみ接続されます。)GNUはsort
並列に動作します。スレッド数は次のように構成できます。--parallel
オプションデフォルトでは、プロセッサごとに1つのスレッドを使用して最大8つまで可能です。 (プロセッサーの数が増えると、より多くのプロセッサーを使用する利点が減ります。、徐々に減少速度は、タスクの並列化の程度に依存します。 )
grep
並列化はまったくありません。 PCREライブラリは、ロックを使用するスレッドから安全な機能を提供し、ロック操作機能がpthreadライブラリにあるため、実際にpthreadライブラリにリンクされます。
大量のデータを処理するときに一般的に並列化の利点を享受する簡単な方法は、データを複数の部分に分割し、その部分を並列に処理することです。 grepの場合は、ファイルサイズを制御可能に保ち(たとえば、ログファイルの場合は十分に頻繁に回転)、各ファイルで別々のgrepインスタンスを呼び出します(たとえば、次のように)GNUパラレル)。 greppingは通常IOバウンド(または非常に複雑な正規表現がある場合、またはGNU grep(パフォーマンスの低下)の一部のUnicodeコーナーケースが発生した場合はCPUバウンド)なので、スレッド数が多いと多くの利点を得る可能性はありません。
答え2
調べるもう1つの方法は、sysdig
プロセスで実行されているシステムコールを調べるなどのものを使用することです。たとえば、rm
(システムコールを介して)スレッドが作成されたことを確認するには、clone
次のようにします。
# sysdig proc.name=rm and evt.type=clone and evt.dir='<'
この実行を通して、私は次のことをしました。
$ mkdir foo
$ cd foo
$ touch {1..9999}
$ rm *
クローンは見えません。スレッドはありません。他のツールを使用してこの実験を繰り返すことはできますが、スレッドがあることを見つけることはできません。
これはclone()
デフォルトでもfork()
あるため、ツールが別のプロセス(たとえばfind ... -exec
)を起動すると、この出力が表示されます。これらのフラグは、「新しいスレッドを作成する」ユースケースとは異なります。
# sysdig proc.name=find and evt.type=clone and evt.dir='<'
...
1068339 18:55:59.702318832 2 find (2960545) < clone res=0 exe=find args=/tmp/foo.-type.f.-exec.rm.{}.;. tid=2960545(find) pid=2960545(find) ptid=2960332(find) cwd= fdlimit=1024 pgft_maj=0 pgft_min=1 vm_size=9100 vm_rss=436 vm_swap=0 comm=find cgroups=cpuset=/.cpu=/user.slice.cpuacct=/user.slice.io=/user.slice.memory=/user.slic... flags=25165824(CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID) uid=1026 gid=1026 vtid=2960545(find) vpid=2960545(find)
答え3
並列に実行する方法については、xargs
またはgnuを参照してください。parallel
しかし、より多くのプロセスが追加されるほど、並列化可能な部分は時間がゼロになる傾向があります。これにより、並列化できない部分が残り、速度が速くなりません。したがって、プロセスを追加してタスクを完了する速度には制限があります。すぐにプロセスを追加しても、あまり差がない状況に達することになります。
その後、通信オーバーヘッドがあります。プロセスを追加すると速度が遅くなります。プロセスの追加による利点がプロセスの追加コストよりも少ないと、プロセスが遅くなる可能性があります。
答え4
デフォルトでは、指定したユーティリティに興味がある場合、これらのコマンドのスレッドバージョンが存在する可能性はほとんどありません。
さらに悪いことは、このバリエーションが存在する場合は、シングルスレッドバージョンよりも遅くなる可能性が高いことです。
これは、名前付きユーティリティがすべて(複数のスレッドで実行されている場合)カーネルの最適化(先読みなど)を損なう可能性がある多くのファイルシステム対話を持っているためです。
たとえば、よく実装されたカーネルはファイルの線形読み取りを検出し、たとえばファイルのgrep
内容を事前にインポートして線形読み取りを生成します。grep
操作は1つまたは2つのディレクトリでmv
行われ、rename
カーネルにディレクトリロックが必要です。非原子的に実装されない限り、これらのディレクトリの別の名前変更操作は同時に発生することはできません。
一方、最も古い無料tar
実装()は、2つの基本的な作業の面で30年間並列化されてきました。 2つのプロセスがあり、2つのプロセス間に共有メモリブロックがあるため、1つのプロセスがアーカイブの読み取り/書き込み操作を実行できます。star
ファイルシステムI / Oの実行中に、他のプロセスがアーカイブの読み取り/書き込み操作を実行できます。
grep
カーネルのファイルシステムプリフェッチは、単一のCPUを使用するよりも複数のCPUを使用する方が速いため、特定の質問に「ほとんどはい」と答えることができます。作業中のファイルがそれほど大きくなく、ファイルがすでにカーネルキャッシュ内にある場合、プリフェッチの利点はありません。
time
注:最新のシェルには、時間を表示するだけでなく、ウォールクロック時間に対するUSERおよびSYS CPU時間の合計比率に基づいてパーセンテージを計算する組み込み機能があります。関連time
出力が100%を超えると、実行中のユーティリティが実際に複数のCPUを活用しているのです。ただし、スレッド化されていないユーティリティの場合、値は通常約105%です。
最後に、並列化はプロセスレベルでも行われ、並列化されたバージョンは非make
並列化されたバージョンよりも簡単に3倍速く実行できます。
プラットフォームで実行中にCPUをシャットダウンできる場合は、CPUをシャットダウンして、n-1
結果を同じシステム上の他の複数のCPU環境と比較することをお勧めします。