Bash

在 bash 文件中並行化 for 循環

  • March 20, 2019

我想在下面的 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 作業將快速連續啟動並同時執行。waitafter 循環確保腳本在所有後台作業完成之前不會退出。

對於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一而不是將其設置為零。

引用自:https://unix.stackexchange.com/questions/486553