xargsパラレルモードを使用して出力を単一のファイルに安全にリダイレクトする

xargsパラレルモードを使用して出力を単一のファイルに安全にリダイレクトする

jqxargsを使用して並列に読み込み、いくつかの簡単な処理を実行し、出力を次のファイルにリダイレクトするbzipped JSONファイルがたくさんあります。

# Number of workers is one less than the number of cores
NUM_WORKERS=$(($(nproc) - 1))
NUM_WORKERS=$((NUM_WORKERS > 0 ? NUM_WORKERS : 1))

# List all bzipped files and process them with xargs in parallel
ls *.jsonl.bz2 | \
xargs -n 1 -P ${NUM_WORKERS} -I {} sh -c "bzcat | jq -c '{id,name}'" > output.jsonl

私は12個のコアプロセッサを持っており、コマンドを実行するとすべて動作します。ただし、出力ファイルには複数のワーカーの出力が混在していることがわかりました。

head -5 output.jsonl
{"id": "0", "name": "Name0"}
{"id": "1", "name": "Name1"}
{"id": "2", {"id": "3", "name": "Name3"}"name": "Name2"}
{"id": "4", "name": "Name4"}
{"id": "5", "name": {"id": "7", "name": "Name7"}"Name5"}
{"id": "6", "name": "Name6"}
{"id": "8", "name": "Name8"}
{"id": "9", "name": "Name9"}

各ワーカーの出力を別々の一時ファイルに書き込んでから後でリンクできることを知っていますが、複数の一時ファイルを作成せずに上記の問題を回避する方法はありますか?

ありがとうございます!

ベストアンサー1

GNU Parallel は一時ファイルを生成しますが、すぐにリンクを解除します。

実際には、データ量が少なく、各ジョブの期間が短い場合、このデータがディスクに到達しないことを意味します(これを使用して発生するかどうかiostat -dkx 1を確認できます)。

リンクされていないファイルはシステムがクラッシュした場合に回復できないため、インテリジェントファイルシステムはこのデータが一貫した方法でディスクに安全に同期されることを保証するために時間を無駄にしないように選択できます。これもより速くすることができます。

--tmpdirRAMが十分な場合は、/dev/shmを指すこともできます。

parallel "bzcat {} | jq -c '{id,name}'" *.jsonl.bz2 > output.jsonl

CPUは十分ですが、RAMが多くなくディスクが遅い場合は、一時ファイルを圧縮する方が高速です。

parallel --compress "bzcat {} | jq -c '{id,name}'" *.jsonl.bz2 > output.jsonl

すべての出力に一時スペースは必要ありません。現在実行中のジョブには一時スペースのみが必要です。したがって、12個のジョブを並列に実行する場合は、12個のファイルのためのスペースだけが必要です。

おすすめ記事