有什么工具可以将bash命令与不同的CPU需求并行化?

时间:2018-08-03 17:43:25

标签: bash parallel-processing

我正在寻找一种工具,使我能够并行处理多达多个内核的bash命令列表,每个bash命令具有不同的CPU要求。

例如,如果我有一台具有3核的计算机,并且具有以下作业列表:

  1. 运行x(使用1个内核)
  2. 运行y(使用2个内核)
  3. 运行z(使用3个内核)

我希望该工具并行运行命令,但要尊重我只有3个内核的事实,因此工作量看起来像

(empty),              (empty), (empty)
Job 1 (using 1 core), (empty), (empty)
Job 1 (using 1 core), Job 2 (using 2 cores)
Job 1 done,           Job 2 (using 2 cores)
(empty),              Job 2 (using 2 cores)
(empty),              Job 2 done
Job 3 (using 3 cores)

1 个答案:

答案 0 :(得分:5)

我的感觉是将此答案分为两个部分。 a)Shell b)Docker并提供一个序言。

nb。最初的问题与运行并行docker容器有关。然后,问题范围扩展到了并行shell脚本的主题。

序言/警告

在具有N个处理元素的并行计算机上运行时,理想情况下的并行编程可将N加速提高一个因子。如果您读过Amdahl’s law,则会注意到由于并行化任务所需的努力,这并不总是正确的。并行任务之间的任何相互依赖关系都将迅速造成复杂性,并可能抵消使操作并行化的努力。

Shell脚本

如果您真的希望通过外壳创建一组并行作业,我个人的建议是使用GNU Parallel。它提供了对CPU和线程属性的极其精细的控制。

它还附带了许多详细的code example

模板示例:

让我们假设一个网站存储的图像如下:

http://www.example.com/path/to/YYYYMMDD_##.jpg

其中YYYYMMDD是日期,而##是数字01-24。这将下载过去30天的图像:

  getit() {
    date=$(date -d "today -$1 days" +%Y%m%d)
    num=$2
    echo wget http://www.example.com/path/to/${date}_${num}.jpg
  }
  export -f getit

  parallel getit ::: $(seq 30) ::: $(seq -w 24)

问题: 上述并行任务方法有什么问题?

答案: 嗯,任务的并行性看起来不错,但是现在性能受到网站的IO带宽的限制...因此,许多并行任务可能会导致整体任务完成速度变慢。

Docker

在docker run命令上,您可以定义可以限制CPU资源的使用

--cpu=n

https://docs.docker.com/config/containers/resource_constraints/#configure-the-default-cfs-scheduler

以下示例仅通过外壳for循环构造启动了一组(假定的)非依赖docker容器。这是一种以并行方式运行一组非依赖容器的典型方法。注意:这些程序是按顺序开始的,但可以独立运行,可以在Docker IO通信背板中建立任何相互依赖关系(即它们可以通过TCP进行通信),尽管坦白地说,您正在就实际尝试的内容进行技术性讨论与并行性有关。 (当心,龙……)

示例模板

  1 #!/bin/bash
  2
  3 n="$1"
  4 if [[ "$n" == "" ]]; then
  5     echo "You did not specify number of parallel runs to launch. Defaulting to 10."
  6     n="10"
  7 fi
  8
  9 mkdir $PWD/openjdks
 10
 11 for i in $(seq 1 $n); do
 12         mkdir $PWD/openjdks/$i
 13         docker run -d\
 14            --name=<name>$i \
 15            --cap-add=SYS_ADMIN \
 16            --cpu=<number of CPU required> \
 17            -v $PWD/openjdks/$i:/tmp \
 18            -e DISTRO=centos \
 19            -r mirror \
 20            -filename java-1.6.0-openjdk-1.6.0.41-1.13.13.1.el7_3.x86_64.rpm \
 21            -path /tmp/java-1.6.0-openjdk-1.6.0.41-1.13.13.1.el7_3.x86_64.rpm \
 22            -log /tmp/mylog.log
 23 done

我希望以上内容能为您指明正确的方向。