Bash 并行运行作业

Bash 并行运行作业,bash,parallel-processing,xargs,Bash,Parallel Processing,Xargs,我希望并行运行大量密集型进程,在这些进程中,我使用for循环遍历不同的参数。对类似问题的许多回答都提到可以使用xargs并行运行进程,但没有一个提到如果每个命令的参数发生变化,是否可以或如何做到这一点 例如(伪代码): 我想并行化intensiveCommand 或者有没有比使用xargs更简单的方法呢?我写了这篇文章,效果非常好——阅读顶部的评论,看看它是如何工作的 #!/bin/bash ####################################################

我希望并行运行大量密集型进程,在这些进程中,我使用for循环遍历不同的参数。对类似问题的许多回答都提到可以使用xargs并行运行进程,但没有一个提到如果每个命令的参数发生变化,是否可以或如何做到这一点

例如(伪代码):

我想并行化intensiveCommand


或者有没有比使用xargs更简单的方法呢?

我写了这篇文章,效果非常好——阅读顶部的评论,看看它是如何工作的

#!/bin/bash
################################################################################
# File: core
# Author: Mark Setchell
# 
# Primitive, but effective tool for managing parallel execution of jobs in the
# shell. Based on, and requiring REDIS.
#
# Usage:
#
# core -i 8 # Initialise to 8 cores, or specify 0 to use all available cores
# for i in {0..63}
# do
#   # Wait for a core, do a process, release core
#   (core -p; process; core -v)&
# done
# wait
################################################################################
function usage {
    echo "Usage: core -i ncores # Initialise with ncores. Use 0 for all cores."
    echo "       core -p        # Wait (forever) for free core."
    echo "       core -v        # Release core."
    exit 1
}

function init {
    # Delete list of cores in REDIS
    echo DEL cores | redis-cli > /dev/null 2>&1
    for i in `seq 1 $NCORES`
    do
       # Add another core to list of cores in REDIS
       echo LPUSH cores 1 | redis-cli > /dev/null 2>&1
    done
    exit 0
}

function WaitForCore {
    # Wait forever for a core to be available
    echo BLPOP cores 0 | redis-cli > /dev/null 2>&1
    exit 0
}

function ReleaseCore {
    # Release or give back a core
    echo LPUSH cores 1 | redis-cli > /dev/null 2>&1
    exit 0
}

################################################################################
# Main
################################################################################
while getopts "i:pv" optname
  do
    case "$optname" in
      "i")
        if [ $OPTARG -lt 1 ]; then
           NCORES=`sysctl -n hw.logicalcpu`;    # May differ if not on OSX, maybe "nproc" on Linux
        else
           NCORES=$OPTARG
        fi
    init $NCORES
        ;;
      "p")
    WaitForCore
        ;;
      "v")
    ReleaseCore
        ;;
      "?")
        echo "Unknown option $OPTARG"
        ;;
    esac
done
usage
举例来说,以下操作需要10秒(不是80秒)来完成16次每次5秒的等待:

core -i 8 
for i in {0..15}
do
   # Wait for a core, do a process, release core
   (core -p ; sleep 5 ; core -v)&
done
wait
你可以用。它有一个
--load
选项,用于避免计算机过载

parallel --load 100% ./intensiveCommand ::: 1 2 3 ::: 1 2 3
u芯数=4#在“每个芯1个槽”中安排得非常紧凑,坚固而简单

#/bin/bash

#use the filedescriptor as a kind of queue to fill the processing slots.

exec 3< <(

    for PARAM_A in 1 2 3
    do
        for PARAM_B in 1 2 3
        do
             echo $PARAM_A $PARAM_B
        done
    done
)

#4 seperate processing slots running parallel 
while read -u 3 PARA PARB; do "intensiveCommand $PARA $PARB" ; done &
while read -u 3 PARA PARB; do "intensiveCommand $PARA $PARB" ; done &
while read -u 3 PARA PARB; do "intensiveCommand $PARA $PARB" ; done &
while read -u 3 PARA PARB; do "intensiveCommand $PARA $PARB" ; done &

#only exit when 100% sure that all processes ended
while pgrep "intensiveCommand" &>"/dev/null" ; do wait ; done
#/bin/bash
#使用filedescriptor作为一种队列来填充处理槽。
执行3
您可以使用“intensiveCommand”在命令末尾添加和签名。这将在parralel中运行作业。是的,但这不考虑负载,对吗?因此,它将继续添加进程,因此它将开始交换进程并降低进程速度。在这种情况下,您可以从uname的输出中解析平均负载,并有条件地运行新进程。是的,安装和运行起来非常容易。其中的键函数为“BLPOP”,它对列表中的项目执行阻塞等待。这允许我精确地控制一次可以运行多少个进程。如果我想要8个,我会在开始的时候把8个项目放在列表中,每次我做一项工作的时候就拿一个,然后在完成后把它还给列表。有没有解释一下这是如何工作的
pgrep-c“intensiveCommand”
统计当前运行的进程列表中“intensiveCommand”的实例数<代码>-ge
表示“大于或等于”。。。行
(…)&
在后台启动某种新流程?除此之外,我对它的工作原理一无所知
number_of_cores=4   #<-- number of processorcores, in my case: 4

for paramA in 1 2 3
do
    for paramB in 1 2 3
    do
        #========== automatic load regulator ==================
        sleep 1
        while [  $( pgrep -c "intensiveCommand" ) -ge "$number_of_cores" ]
        do
            kill -SIGSTOP $$
        done
        #======================================vvvvvvvvvvvvvvvv            

        ( ./intensiveCommand $paramA $paramB ; kill -SIGCONT $$ ) &

    done
done
#/bin/bash

#use the filedescriptor as a kind of queue to fill the processing slots.

exec 3< <(

    for PARAM_A in 1 2 3
    do
        for PARAM_B in 1 2 3
        do
             echo $PARAM_A $PARAM_B
        done
    done
)

#4 seperate processing slots running parallel 
while read -u 3 PARA PARB; do "intensiveCommand $PARA $PARB" ; done &
while read -u 3 PARA PARB; do "intensiveCommand $PARA $PARB" ; done &
while read -u 3 PARA PARB; do "intensiveCommand $PARA $PARB" ; done &
while read -u 3 PARA PARB; do "intensiveCommand $PARA $PARB" ; done &

#only exit when 100% sure that all processes ended
while pgrep "intensiveCommand" &>"/dev/null" ; do wait ; done