zoukankan      html  css  js  c++  java
  • shell 设置进程数运行

    问题描述


    在服务器上提交任务时,需要限制运行的核的数目。程序本身是单线程的,但是不同的输入参数需要跑很多组,粗暴的方法是开多个终端,不断地去提交任务。但这比较麻烦,可以用 shell 实现。

    基础


    首先看第一种 shell 写法

     1 #! /bin/bash
     2 
     3 start=`date +%s`
     4 
     5 for i in {0..3}
     6 do
     7     echo sucess
     8     sleep 2
     9 done
    10 
    11 end=`date +%s`
    12 echo "time: `expr $end - $start`"
    • 如何提取当前时间,date +%s,返回值是从 1970 年至今的秒数。
    • for 循环的写法。
    • shell 中数学运算,注意 start 与 end 之间需要空格。

    该程序的运行结果是 8 s,如果放在后台运行,则只需要 2 s,代码如下

     1 #! /bin/bash
     2 
     3 start=`date +%s`
     4 
     5 for i in {0..3}
     6 do
     7     {
     8         echo sucess
     9         sleep 2
    10     } &
    11 done
    12 wait
    13 
    14 end=`date +%s`
    15 echo "time: `expr $end - $start`"
    • 需要使用 {} 将主执行程序包括,用 & 将其放入后台。
    • 需要 wait 命令等待所有命令执行完成,不然系统会直接继续往下走。

    这样做实现了多线程并发,但是问题是不能控制使用的进程数。因此引入了管道文件操作符

    管道

    • 比如 hexdump Run0035.bin | less 中的 | 就是管道,用于连接两个命令间的数据。
    • 管道的特点是,如果管道中没有数据,那么取管道数据的操作就会停滞,直到管道中有数据;同样写管道的操作也是如此,如果没有读取操作,那么写操作也会停滞。意思就是管道需要既有读操作,也有写操作。
    • 使用 mkfifo 命令可以创建有名管道

    文件操作符

    • 通过文件操作符,可以控制 linux 系统中 /proc 文件夹下的内容,从而控制 linux 中进程的运行。

    代码



    1
    #!/usr/bin/env bash 2 3 #设置变量 4 beta=0.25 5 gammaList=(22.0 24.0 26.0 28.0 30.0 32.0 34.0 36.0 38.0) 6 moiList=(4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0 16.0 17.0 18.0 19.0 20.0 21.0 22.0 23.0 24.0 25.0 26.0 27.0 28.0 29.0) 7 8 start=`date +%s` 9 thread_num=36 10 11 trap "exec 1000>&-;exec 1000<&-;exit 0" 2 12 tmpfifo=$$.fifo 13 mkfifo $tmpfifo 14 exec 1000<>$tmpfifo 15 rm -rf $tmpfifo 16 17 for (( i=0; i<$thread_num; i++ )) 18 do 19 echo >&1000 20 done 21 22 for gamma in ${gammaList[@]} 23 do 24 if [ ! -d "gamma"$gamma ]; then 25 mkdir gamma$gamma 26 fi 27 outfile=`printf "terminal-out-%s" "$gamma"` 28 for moi in ${moiList[@]} 29 do 30 read -u1000 31 { 32 sh auto-run.sh $beta $gamma $moi > $outfile 33 echo >&1000 34 }& 35 done 36 done 37 38 wait 39 end=`date +%s` 40 echo "times: `expr $end - $start`"
    • 第 9 行,设置使用进程数.
    • 第 11 行,表示脚本在运行过程中,如果接收到 ctrl+c,则则关闭文件描述符 1000 的读写,并正常退出。其中 exec >1000&- 代表关闭对文件描述符 1000 的写,exec <1000&- 代表关闭对文件描述符 1000 的读,trap 用于接受中断命令,2 代表 ctrl+c.
    • 12 ~ 14 行,创建一个管道文件 PID.fifo,并与文件描述符 1000 做读写的绑定。如此一来,对文件描述符 1000 的操作就相当于对管道文件的操作,且该文件描述符又有管道的特性,即读写操作必须同时存在,否则会停滞。
    • 第 15 行,将管道文件删除(不明白)
    • 17 ~ 20 行,向文件描述符 1000 写入相应进程数的空行,用于控制进程数。
    • 22 ~ 36 行,主体部分。第 30 行,从文件描述符 1000 读取 1 行,第 31 ~ 34 行,后台执行其中的命令,当第 32 行执行结束后,再向文件描述符 1000 中写入一个空行。结果就是,先读取了文件描述符 1000 中所有的行,读取完后因为没有写入,由于管道性质,该行为被阻塞,因此不会再读取,即不会再执行 read -u1000,但后台若有第 32 行的命令执行结束,便会执行第 33 行的写入命令,写入后 read -u1000 操作便不会阻塞,于是每当跑完一个后台,便可以提交下一个后台。
    • 38 ~ 40 行,等待所有命令执行完成,输出耗时。
  • 相关阅读:
    webdav srs相关
    How To Configure WebDAV Access with Apache on Ubuntu 14.04
    ubuntu 编译lighttpd
    srs编译及推流测试
    Compile pciutils (lspci, setpci) in Windows x86,在 Windows x86 平台下编译 pciutils (lspci, setpci)
    mingw MSYS2 区别
    Qt之美(三):隐式共享
    Qt之美(二):元对象
    Qt之美(一):d指针/p指针详解
    C++的栈空间和堆空间
  • 原文地址:https://www.cnblogs.com/kurrrr/p/13160130.html
Copyright © 2011-2022 走看看