歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Bash腳本實現批量作業並行化

在Linux下運行作業時, 經常會遇到以下情形: 有大量作業需要運行,完成每個作業所需要的時間也不是很長。 如果我們以串行方式來運行這些作業,可能要耗費較長的時間; 若采用並行方式運行則可以大大節約運行時間。再者, 目前的計算機絕大部分都是多核架構, 要想充分發揮它們的計算能力也需要並行化。總結網上看到的資料,利用Bash腳本,可以采用下面幾種方法實現批量作業的並行化。注意,下面論述中將不會區分進程和線程,也不會區分並行和並發。

1. 采用GNU的paralle程序

parallel是GNU專門用於並行化的一個程序, 對於簡單的批量作業並行化非常合適. 使用parallel不需要編寫腳本, 只需在原命令的基礎上簡單地加上parallel就可以了. 所以, 如果能用paralle並行化你的作業, 請優先使用. 有關paralle的詳細說明, 請參考其官方文檔.

2. 最簡單的並行化方法:&+wait

利用Bash的後台運行&和wait函數, 可實現最簡單的批量作業並行化.

如下面的代碼, 串行執行大約需要10秒

改為下面的簡單並行代碼理想情況下可將運行時間壓縮到3秒左右

3. 進程數可控的並行化方法(1): 模擬隊列

使用Bash腳本同時運行多個進程並無困難, 主要存在的問題是如何控制同時運行的進程數目. 上面的簡單並行化方法使用時進程數無法控制, 因而功能有限, 因為大多數時候我們需要運行的作業數遠遠超過可用處理器數, 這種情況下若大量作業同時在後台運行, 會導致運行速度變慢, 並行效率大大下降. 一種簡單的解決方案就是模擬一個限定最大進程數的隊列, 以進程PID做為隊列元素, 每隔一定時間檢查隊列, 若隊列中有作業完成, 則添加新的作業到隊列中. 這種方法還可以避免由於不同作業耗時不同而產生的無用等待. 下面是根據網上的代碼改寫的一種實現. 實用性更強的代碼, 請參考原文.

一個更簡潔的方法是記錄PID到數組, 通過檢查PID存在與否以確定作業是否運行完畢. 可實現如下

3. 進程數可控的並行化方法(2): 命名管道

上面的並行化方法也可利用命名管道來實現, 命名管道是Linux下進程間進行通訊的一種方法, 也稱為先入先出(fifo,first in first out)文件. 具體方法是創建一個fifo文件, 作為進程池, 裡面存放一定數目的"令牌".作業運行規則如下: 所有作業排隊依次領取令牌; 每個作業運行前從進程池中領取一塊令牌, 完成後再歸還令牌; 當進程池中沒有令牌時, 要運行的作業只能等待. 這樣就能保證同時運行的作業數等於令牌數. 前面的模擬隊列方法實際就是以PID作為令牌的實現.

據我已查看的資料, 這種方法在網絡上討論最多. 實現也很簡潔, 但理解其代碼需要的Linux知識較多. 下面是我改寫的示例代碼及其注釋.

注意:

(1) exec6$Pfifo 這一句很重要, 若無此語句, 向$Pfifo寫入數據時, 程序會被阻塞, 直到有read讀出了文件中的數據為止. 而執行了此語句, 就可以在程序運行期間不斷向文件寫入數據而不會阻塞, 並且數據會被保存下來以供read讀出.

(2) 當$Pfifo中已經沒有數據時,read無法讀到數據, 進程會被阻塞在read操作上, 直到有子進程運行結束,向$Pfifo寫入一行.

(3) 核心執行部分也可使用如下方式

{}和()的區別在shell是否會衍生子進程

(4) 此方法在目前的Cygwin(版本1.7.27)下無法使用, 因其不支持雙向命名管道. 有人提到一個解決方案, 使用兩個文件描述符來替代單個文件描述符, 但此方法我沒有測試成功。

bash的登錄與歡迎信息:/etc/issue,/etc/motd  http://www.linuxidc.com/Linux/2014-08/105419.htm

Bash常用的幾個配置文件 http://www.linuxidc.com/Linux/2014-08/105202.htm

Bash腳本15分鐘進階教程 http://www.linuxidc.com/Linux/2014-04/100750.htm

10個 Linux/Unix下 Bash 和 KSH shell 的作業控制實例 http://www.linuxidc.com/Linux/2014-03/98159.htm

Ubuntu下shell腳本運行異常:Bash和dash的區別 http://www.linuxidc.com/Linux/2013-10/91100.htm

Bash腳本之for語句if語句以及各種測試語句 http://www.linuxidc.com/Linux/2013-07/87922.htm

什麼是Bash Shell的內建(build in)命令 http://www.linuxidc.com/Linux/2013-06/86039.htm

分享有用的 bash 別名和函數  http://www.linuxidc.com/Linux/2015-01/111178.htm

Copyright © Linux教程網 All Rights Reserved