美文网首页
Shell 使用多线程提交任务-FIFO

Shell 使用多线程提交任务-FIFO

作者: caokai001 | 来源:发表于2020-12-01 15:20 被阅读0次

    参考:

    学习snakemake,三步轻松搭建生信流程!
    linux shell 多线程执行程序
    [Linux 1] Shell“ 多线程”,提高工作效率

    目前snakemake 对整合生信流程比较友好,shell流程写惯了也还行。感觉在没有作业提交系统的服务器上,使用snakemake 可以很好的控制核心数目,保证服务器可能正常运行,而不是超负荷状态。shell脚本一般都是for循环进行批量,假如存在几百个样本一次批量提交到后台,可能会卡死。

    • 发现shell也可以支持多线程提交,就记录下来。
    • Shell中并没有真正意义的多线程,要实现多线程可以启动多个后端进程,最大程度利用cpu性能

    1 顺序执行的代码

    #!/bin/bash
    date
    for i in `seq 1 5`
    do
    {
        echo "sleep 5"
        sleep 5
    }
    done
    date
    

    结果

    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 实现“多进程”实现
    #!/bin/bash
    date
    for i in `seq 1 5`
    do
    {
        echo "sleep 5"
        sleep 5
    } &
    done
    wait  ##等待所有子后台进程结束
    date
    
    

    结果

    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 对于大量处理任务如何实现启动后台进程的数量可控?

    • 简单的方法可以使用2层for/while循环实现,每次wait内层循环的多个后台程序执行完成。
    • 但是这种方式的问题是,如果内层循环有“慢节点”可能导致整个任务的执行执行时间长。
    #!/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  ##等待所有子后台进程结束
    
    
    }
    done
    date
    

    结果

    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)实现每次启动后台进程数量可控。

    : 经常需要修改的参数:

    • thread_num=5 # 定义最大线程数
    • 修改自己的任务


      image.png
    #!/bin/bash
    # bam to bed
    
    start_time=`date +%s`  #定义脚本运行的开始时间
    
    tmp_fifofile="/tmp/$$.fifo"
    mkfifo $tmp_fifofile   # 新建一个FIFO类型的文件
    exec 6<>$tmp_fifofile  # 将FD6指向FIFO类型
    rm $tmp_fifofile  #删也可以,
    
    thread_num=5  # 定义最大线程数
    
    #根据线程总数量设置令牌个数
    #事实上就是在fd6中放置了$thread_num个回车符
    for ((i=0;i<${thread_num};i++));do
        echo
    done >&6
    
    for i in `seq 1 10 ` # 需要处理的所有情况
    do
        # 一个read -u6命令执行一次,就从FD6中减去一个回车符,然后向下执行
        # 当FD6中没有回车符时,就停止,从而实现线程数量控制
        read -u6
        {
        
        ### Start 输入自己的命令
            echo "great" # 可以用实际命令代替
            echo "$i is running"
            sleep $i
        ### End 输入自己的命令
            
            
            echo >&6 # 当进程结束以后,再向FD6中加上一个回车符,即补上了read -u6减去的那个
        } &
    done
    
    wait # 要有wait,等待所有线程结束
    
    stop_time=`date +%s` # 定义脚本运行的结束时间
    echo "TIME:`expr $stop_time - $start_time`" # 输出脚本运行时间
    
    exec 6>&- # 关闭FD6
    echo "over" # 表示脚本运行结束
    
    

    结果:

    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系统,不需要这么麻烦限制任务提交数目,或者CPU核心数目
    • snakemake比较容易解决核心问题

    相关文章

      网友评论

          本文标题:Shell 使用多线程提交任务-FIFO

          本文链接:https://www.haomeiwen.com/subject/hqlswktx.html