Bash

BASH:並行執行

  • May 6, 2017

我有一個 bash 腳本,它將三個長度相等的數組作為輸入METHODSINFILESOUTFILES.

此腳本將METHODS[i]解決問題INFILES[i]並將結果保存到OUTFILES[i], 對於所有索引i( 0 <= i <= length-1)。

中的每個元素METHODS都是以下形式的字元串:

$HOME/program/solver -a <method>

其中求解器是一個可以如下呼叫的程序:

$HOME/program/solver -a <method> -m <input file> -o <output file> --timeout <timeout in seconds>

該腳本並行解決了所有問題,並將每個實例的執行時間限制設置為 1 小時(但有些方法可以很快解決一些問題),如下所示:

#!/bin/bash
source METHODS
source INFILES
source OUTFILES

start=`date +%s`

## Solve in PARALLEL
for index in ${!OUTFILES[*]}; do 
   (alg=${METHODS[$index]}
   infile=${INFILES[$index]}
   outfile=${OUTFILES[$index]}

   ${!alg}  -m $infile -o $outfile --timeout 3600) &
done
wait


end=`date +%s`

runtime=$((end-start))
echo "Total runtime = $runtime (s)"
echo "Total number of processes = ${#OUTFILES[@]}"

在上面我有length = 619. 我將這個 bash 送出給一個有 70 個可用處理器的集群,它最多需要 9 個小時才能完成所有任務。然而,實際情況並非如此。使用該top命令進行調查時,我發現只有兩三個程序在執行(state = R),而其他所有程序都在休眠(state = D)。

請問我做錯了什麼?

此外,我了解到GNU 並行對於執行並行作業會更好。我如何將它用於上述任務?

非常感謝您的幫助!

**更新:**我第一次嘗試使用 GNU 並行:

想法是將所有命令寫入文件,然後使用 GNU 並行執行它們:

#!/bin/bash
source METHODS
source INFILES
source OUTFILES

start=`date +%s`    

## Write to file
firstline=true
for index in ${!OUTFILES[*]}; do 
   (alg=${METHODS[$index]}
   infile=${INFILES[$index]}
   outfile=${OUTFILES[$index]}
   if [ "$firstline" = true ] ; then
       echo "${!alg}  -m $infile -o $outfile --timeout 3600" > commands.txt
       firstline=false
   else
       echo "${!alg}  -m $infile -o $outfile --timeout 3600" >> commands.txt
   fi
done

## Solve in PARALLEL
time parallel :::: commands.txt

end=`date +%s`

runtime=$((end-start))
echo "Total runtime = $runtime (s)"
echo "Total number of processes = ${#OUTFILES[@]}"

你怎麼看?

**更新 2:**我正在使用 GNU 並行並遇到同樣的問題。這是輸出top

top - 02:05:25 up 178 days,  8:16,  2 users,  load average: 62.59, 59.90, 53.29
Tasks: 596 total,   7 running, 589 sleeping,   0 stopped,   0 zombie
Cpu(s): 12.9%us,  0.9%sy,  0.0%ni, 63.3%id, 22.9%wa,  0.0%hi,  0.1%si,  0.0%st
Mem:  264139632k total, 260564864k used,  3574768k free,     4564k buffers
Swap: 268420092k total, 80593460k used, 187826632k free,    53392k cached

 PID USER     PR  NI  VIRT  RES  SHR S %CPU %MEM   TIME+   COMMAND
28542 khue     20   0 7012m 5.6g 1816 R  100  2.2  12:50.22 opengm_min_sum
28553 khue     20   0 11.6g  11g 1668 R  100  4.4  17:37.37 opengm_min_sum
28544 khue     20   0 13.6g 8.6g 2004 R  100  3.4  12:41.67 opengm_min_sum
28549 khue     20   0 13.6g 8.7g 2000 R  100  3.5   2:54.36 opengm_min_sum
28551 khue     20   0 11.6g  11g 1668 R  100  4.4  19:48.36 opengm_min_sum
28528 khue     20   0 6934m 4.9g 1732 R   29  1.9   1:01.13 opengm_min_sum
28563 khue     20   0 7722m 6.7g 1680 D    2  2.7   0:56.74 opengm_min_sum
28566 khue     20   0 8764m 7.9g 1680 D    2  3.1   1:00.13 opengm_min_sum
28530 khue     20   0 5686m 4.8g 1732 D    1  1.9   0:56.23 opengm_min_sum
28534 khue     20   0 5776m 4.6g 1744 D    1  1.8   0:53.46 opengm_min_sum
28539 khue     20   0 6742m 5.0g 1732 D    1  2.0   0:58.95 opengm_min_sum
28548 khue     20   0 5776m 4.7g 1744 D    1  1.9   0:55.67 opengm_min_sum
28559 khue     20   0 8258m 7.1g 1680 D    1  2.8   0:57.90 opengm_min_sum
28564 khue     20   0 10.6g  10g 1680 D    1  4.0   1:08.75 opengm_min_sum
28529 khue     20   0 5686m 4.4g 1732 D    1  1.7   1:05.55 opengm_min_sum
28531 khue     20   0 4338m 3.6g 1724 D    1  1.4   0:57.72 opengm_min_sum
28533 khue     20   0 6064m 5.2g 1744 D    1  2.1   1:05.19 opengm_min_sum

(以上opengm_min_sumsolver

我猜有些程序消耗了太多資源,以至於其他程序沒有任何剩餘並進入 D 狀態?

評論摘要:機器速度很快,但沒有足夠的記憶體來並行執行所有內容。另外這個問題需要讀取大量數據,磁碟頻寬不夠,所以cpu大部分時間都是空閒的等待數據。

重新安排任務會有所幫助。

尚未研究壓縮數據是否可以提高有效磁碟 I/O 頻寬。

從版本 20160422 開始,您可以執行以下操作:

## Solve in PARALLEL
parallel {1} -m {2} -o {3} --timeout 3600 ::: "${METHODS[@]}" :::+ "${INFILES[@]}" :::+ "${OUTFILES[@]}"

如果您有舊版本:

## Solve in PARALLEL
parallel --xapply {1} -m {2} -o {3} --timeout 3600 ::: "${METHODS[@]}" ::: "${INFILES[@]}" ::: "${OUTFILES[@]}"

花一個小時走過man parallel_tutorial。您的命令行會因此而愛上您。

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