參考:
學(xué)習(xí)snakemake唐瀑,三步輕松搭建生信流程!
linux shell 多線程執(zhí)行程序
[Linux 1] Shell“ 多線程”聚假,提高工作效率
目前snakemake
對(duì)整合生信流程比較友好分蓖,shell流程寫慣了也還行欧啤。感覺在沒有作業(yè)提交系統(tǒng)的服務(wù)器上拿愧,使用snakemake
可以很好的控制核心數(shù)目贼急,保證服務(wù)器可能正常運(yùn)行蜗元,而不是超負(fù)荷狀態(tài)拾因。shell
腳本一般都是for
循環(huán)進(jìn)行批量旺罢,假如存在幾百個(gè)樣本一次批量提交到后臺(tái),可能會(huì)卡死绢记。
- 發(fā)現(xiàn)
shell
也可以支持多線程
提交扁达,就記錄下來。 - Shell中并沒有真正意義的多線程蠢熄,要實(shí)現(xiàn)多線程可以啟動(dòng)多個(gè)后端進(jìn)程跪解,最大程度利用cpu性能
1 順序執(zhí)行的代碼
#!/bin/bash
date
for i in `seq 1 5`
do
{
echo "sleep 5"
sleep 5
}
done
date
結(jié)果
Tue Dec 1 14:27:49 CST 2020
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
Tue Dec 1 14:28:14 CST 2020
2 并行代碼
- 使用
'&'+wait
實(shí)現(xiàn)“多進(jìn)程”實(shí)現(xiàn)
#!/bin/bash
date
for i in `seq 1 5`
do
{
echo "sleep 5"
sleep 5
} &
done
wait ##等待所有子后臺(tái)進(jìn)程結(jié)束
date
結(jié)果
Tue Dec 1 14:29:01 CST 2020
sleep 5
sleep 5
sleep 5
sleep 5
sleep 5
Tue Dec 1 14:29:06 CST 2020
3 對(duì)于大量處理任務(wù)如何實(shí)現(xiàn)啟動(dòng)后臺(tái)進(jìn)程的數(shù)量可控?
- 簡(jiǎn)單的方法可以使用2層
for/while
循環(huán)實(shí)現(xiàn)签孔,每次wait
內(nèi)層循環(huán)的多個(gè)后臺(tái)程序執(zhí)行完成叉讥。 - 但是這種方式的問題是,如果內(nèi)層循環(huán)有“慢節(jié)點(diǎn)”可能導(dǎo)致整個(gè)任務(wù)的執(zhí)行執(zhí)行時(shí)間長(zhǎng)饥追。
#!/bin/bash
date
for i in `seq 1 3`
do
{
for j in `seq 1 5`
do
{
echo "$i : sleep 5"
sleep 5
} &
done
wait ##等待所有子后臺(tái)進(jìn)程結(jié)束
}
done
date
結(jié)果
Tue Dec 1 14:16:51 CST 2020
1 : sleep 5
1 : sleep 5
1 : sleep 5
1 : sleep 5
1 : sleep 5
2 : sleep 5
2 : sleep 5
2 : sleep 5
2 : sleep 5
2 : sleep 5
3 : sleep 5
3 : sleep 5
3 : sleep 5
3 : sleep 5
3 : sleep 5
Tue Dec 1 14:17:06 CST 2020
4.使用命名管道(fifo)實(shí)現(xiàn)每次啟動(dòng)后臺(tái)進(jìn)程數(shù)量可控图仓。
注
: 經(jīng)常需要修改的參數(shù):
thread_num=5 # 定義最大線程數(shù)
-
修改自己的任務(wù)
image.png
#!/bin/bash
# bam to bed
start_time=`date +%s` #定義腳本運(yùn)行的開始時(shí)間
tmp_fifofile="/tmp/$$.fifo"
mkfifo $tmp_fifofile # 新建一個(gè)FIFO類型的文件
exec 6<>$tmp_fifofile # 將FD6指向FIFO類型
rm $tmp_fifofile #刪也可以,
thread_num=5 # 定義最大線程數(shù)
#根據(jù)線程總數(shù)量設(shè)置令牌個(gè)數(shù)
#事實(shí)上就是在fd6中放置了$thread_num個(gè)回車符
for ((i=0;i<${thread_num};i++));do
echo
done >&6
for i in `seq 1 10 ` # 需要處理的所有情況
do
# 一個(gè)read -u6命令執(zhí)行一次但绕,就從FD6中減去一個(gè)回車符救崔,然后向下執(zhí)行
# 當(dāng)FD6中沒有回車符時(shí)惶看,就停止,從而實(shí)現(xiàn)線程數(shù)量控制
read -u6
{
### Start 輸入自己的命令
echo "great" # 可以用實(shí)際命令代替
echo "$i is running"
sleep $i
### End 輸入自己的命令
echo >&6 # 當(dāng)進(jìn)程結(jié)束以后六孵,再向FD6中加上一個(gè)回車符纬黎,即補(bǔ)上了read -u6減去的那個(gè)
} &
done
wait # 要有wait,等待所有線程結(jié)束
stop_time=`date +%s` # 定義腳本運(yùn)行的結(jié)束時(shí)間
echo "TIME:`expr $stop_time - $start_time`" # 輸出腳本運(yùn)行時(shí)間
exec 6>&- # 關(guān)閉FD6
echo "over" # 表示腳本運(yùn)行結(jié)束
結(jié)果:
great
1 is running
great
great
2 is running
3 is running
great
4 is running
great
5 is running
great
6 is running
great
7 is running
great
8 is running
great
9 is running
great
10 is running
TIME:15
over
思考
- 一般情況下集群有PBS系統(tǒng)劫窒,不需要這么麻煩限制任務(wù)提交數(shù)目本今,或者CPU核心數(shù)目
- snakemake比較容易解決核心問題