Bash
在 bash 文件中並行化 for 循環
我想在下面的 bash 腳本中並行化 for 循環。
我有兩個 Matlab 腳本
1) 主.m
clear rng default P=2; grid=randn(2,3); jobs=1;
2) 調頻
sgetasknum_grid=grid(jobs*(str2double(getenv('SGE_TASK_ID'))-1)+1: str2double(getenv('SGE_TASK_ID'))*jobs,:); %jobsx3 result=sgetasknum_grid+1; filename = sprintf('result.%d.mat', ID); save(filename, 'result') exit
我想做的事:
- 我想執行 main.m;
- 然後,我想並行執行兩次 fm
- 一切都應該在節點A上執行
這是我沒有並行化的版本
**1)**我將 main.m 和 fm 保存到名為 My_folder 的文件夾中
**2)**我如下創建 bash 文件 td.sh 並將其保存到文件夾 My_folder
#$ -S /bin/bash #$ -l h_vmem=5G #$ -l tmem=5G #$ -l h_rt=480:0:0 #$ -cwd #$ -j y #$ -N try date hostname export SGE_TASK_ID for SGE_TASK_ID in {1..2} do #Output the Task ID echo "Task ID is $SGE_TASK_ID" /share/.../matlab -nodisplay -nodesktop -nojvm -nosplash -r "main; ID=$SGE_TASK_ID; f; exit" done
**3)**我進入終端並輸入
ssh username@A
, 然後cd /.../My_folder
, 然後bash td.sh
為了並行化,本論壇中的許多答案建議使用
parallel
. 我猜 bash 文件看起來像下面這樣#$ -S /bin/bash #$ -l h_vmem=5G #$ -l tmem=5G #$ -l h_rt=480:0:0 #$ -cwd #$ -j y #$ -N try date hostname export SGE_TASK_ID SGE_TASK_ID={1..2} echo "$SGE_TASK_ID" | parallel -P 2 /share/.../matlab -nodisplay -nodesktop -nojvm -nosplash -r "main; ID=$SGE_TASK_ID; f; exit"
但是,這是我在終端上遇到的錯誤
A.local td.sh: line 16: parallel: command not found
我了解可能是
parallel
機器中缺少“軟體”。我可以安裝它嗎?如果可以,如何安裝?還是應該由系統管理員安裝?或者,您有其他建議parallel
嗎?更新:嘗試實現下面第二個答案的腳本
#!/bin/bash -l #$ -S /bin/bash #$ -l h_vmem=5G #$ -l tmem=5G #$ -l h_rt=480:0:0 #$ -cwd #$ -j y #$ -N try date hostname export SGE_TASK_ID SGE_TASK_ID={1..2} echo -e SGE_TASK_ID | xargs -I {} -P 4 /share/.../matlab -nodisplay -nodesktop -nojvm -nosplash -r "main; ID={}; f; exit"
這是我得到的錯誤資訊
Undefined function or variable 'SGE_TASK_ID'.
在您的循環中,在後台啟動 Matlab 作業,然後等待它們在循環後完成:
for SGE_TASK_ID in 1 2; do printf 'Task ID is %d\n' "$SGE_TASK_ID" /share/.../matlab -nodisplay -nodesktop -nojvm -nosplash \ -r "main; ID=$SGE_TASK_ID; f; exit" & done wait
Matlab 作業將快速連續啟動並同時執行。
wait
after 循環確保腳本在所有後台作業完成之前不會退出。對於
J
允許您N
並行執行作業的作業:SGE_TASK_ID=1 n=0 while [ "$SGE_TASK_ID" -le "$J" ]; do if [ "$n" -eq "$N" ]; then wait # waits for the N started jobs to finish n=0 fi printf 'Task ID is %d\n' "$SGE_TASK_ID" /share/.../matlab -nodisplay -nodesktop -nojvm -nosplash \ -r "main; ID=$SGE_TASK_ID; f; exit" & SGE_TASK_ID=$(( SGE_TASK_ID + 1 )) n=$(( n + 1 )) done wait
另一種變體是等待單個後台作業在循環的
if
-statement 內完成,wait -n
並僅減n
一而不是將其設置為零。