私はxargs
を使用してpythonスクリプトを呼び出し、約3,000万の小さなファイルを処理しています。xargs
を使用してプロセスを並列化したいと思っています。コマンドは使用は:
find ./data -name "*.json" -print0 |
xargs -0 -I{} -P 40 python Convert.py {} > log.txt
基本的に、Convert.py
は小さなjsonファイル(4kb)を読み取り、処理を行って別の4kbファイルに書き込みます。 40 CPUコアのサーバーで実行しています。また、このサーバーでは他のCPU負荷の高いプロセスは実行されていません。
Htopを監視することで(ところで、CPUパフォーマンスを監視する他の良い方法はありますか?)、-P 40
が期待されるほど速くないことがわかりました。場合によっては、すべてのコアがフリーズして3〜4秒間ほぼゼロになり、その後60〜70%に回復します。次に、並列プロセスの数を-P 20-30
まで減らしますが、それでもまだそれほど高速ではありません。理想的な動作は、線形スピードアップである必要があります。 xargsの並列使用に関する提案はありますか?
私はあなたの問題がpythonであることを喜んで賭けます。各ファイルでどのような処理が行われているかは言いませんでしたが、データのメモリ内処理だけを実行していると仮定すると、実行時間は3000万を起動することによって支配されますpython =仮想マシン(インタープリター)。
pythonプログラムを再構成してファイルのリストを1つだけではなく取得できる場合は、パフォーマンスが大幅に向上します。その後、xargsを使用してさらにパフォーマンスを向上させることができます。たとえば、 、40プロセス、それぞれ1000ファイルを処理:
find ./data -name "*.json" -print0 |
xargs -0 -L1000 -P 40 python Convert.py
pythonは悪い/遅い言語であると言っているわけではありません。起動時間に対して最適化されていないだけです。仮想マシンベースまたはインタープリター型の言語でこれが見られます。Java、プログラムがCで記述されている場合でも、各ファイルを処理するために個別のオペレーティングシステムプロセスを開始するコストはかかりますが、はるかに少なくなります。
そこから-P
をいじって、もう少しスピードを上げることができるかどうかを確認できます。おそらく、データの読み取り/書き込み中にプロセスの数を増やしてアイドルプロセッサを利用することによります。
したがって、まず、制約を検討します。
各ジョブの制約は何ですか? I/Oの場合、おそらくI/Oの制限に達するまで、CPUコアあたりの複数のジョブを回避できますが、CPUに負荷がかかる場合、CPUコアよりも多くのジョブを同時に無意味に実行するよりも悪くなります。
これらのことについての私の理解は、 GNU Parallel を使用すると、ジョブのキューなどをよりよく制御できるということです。
2つの違いの詳細については、 GNUパラレルvs&(背景を意味する)vs xargs -P を参照してください。
他の人が言ったように、あなたがI/Oバウンドであるかどうかを確認してください。また、xargsのマニュアルページでは、-n
と-P
の併用を推奨していますが、並列で実行されているConvert.py
プロセスの数については触れていません。
提案として、I/Oバウンドの場合は、SSDブロックデバイスを使用するか、tmpfsで処理を行うことをお勧めします(もちろん、この場合、十分なメモリを確認して、tmpfsによるスワップを回避する必要があります)プレッシャー(と思います)と、そもそもデータをそこにコピーするオーバーヘッド)。