我正在嘗試以不同的方式並行處理輸入,在輸入結果時寫出結果行。
# process_parallel.sh
read input
parallel --colsep ' ' --linebuffer 'echo $input | {}' \
::: 'python process1.py' ./process2.sh ./process3
上下文可以歸結為這樣:
(sleep 1; echo "short input arriving late") | ./process_parallel.sh | ./collate_results.sh
上述方法有效,但有一個重要的缺點:在讀取輸入之前,進程不會啟動。我想立即啟動它們,因為這可能需要一段時間,然後將其完整的標準輸入並行管道傳輸到它們中的每一個。
我該如何實現這個目標?
答案1
GNU Parallel 已投入大量工作,使其在沒有資料可運行時不會啟動新作業。這是由於某些程式如果沒有得到任何輸入就會嚴重失敗。所以你將違背 GNU Parallel 的設計。
要複製輸入,您可以使用tee
並處理替換:
cat namedpipe_or_file | tee >(process1) >(process2) >(process3) >/dev/null
它將立即開始process1
、process2
、process3
。但是,輸出可以混合,因此如果必須使用輸出,您應該將其重定向到不同的檔案:
cat namedpipe_or_file | tee >(process1 > out1) >(process2 > out2) >(process3 > out3) >/dev/null
答案2
有兩個包裝器腳本:首先,修改 process_parallel.sh,以便指示每個進程從三個檔案(例如 file1、file2、file3)讀取其輸入。
現在編寫第二個包裝器腳本,它將其標準輸入並行發送到三個文件,如下所示:
#!/bins/bash
#parallelise input
# let's call this file parallelise
parallel -j 3 -- "echo $1 > file1" "echo $1 > file2" "echo $1 file3"
現在你開始你的事情:
./process_parallel_sh; cat InputFile | parallelise;
答案3
Parallel 有一個--tee
選項,可以這樣使用:
(sleep 1; echo "short input arriving late") |\
parallel --colsep ' ' --linebuffer --pipe --tee ::: 'python process1.py' ./process2.sh ./process3 |\
./collate_results.sh