Linux 并行高效地运行多个作业

Linux 并行高效地运行多个作业,linux,parallel-processing,Linux,Parallel Processing,操作系统:分操作系统 我有一些30000作业(或脚本)要运行。每个作业需要3-5分钟。我有48个CPU(nproc=48)。我可以使用40个CPU并行运行40个作业。请建议一些脚本或工具可以通过并行运行每个40个作业来处理30000个作业 我所做的: 我创建了40个不同的文件夹,并通过为每个目录创建一个shell脚本并行执行作业 我想知道下次处理这类工作的更好方法 只要执行这些脚本,Linux就会在内部将这些任务正确地分配给可用的CPU。这取决于Linux任务调度程序。但是,如果需要,也可以使

操作系统:分操作系统

我有一些
30000
作业(或脚本)要运行。每个作业需要3-5分钟。我有
48个CPU(nproc=48)
。我可以使用
40个CPU并行运行40个作业。请建议一些脚本或工具可以通过并行运行每个40个作业来处理30000个作业

我所做的:

  • 我创建了40个不同的文件夹,并通过为每个目录创建一个shell脚本并行执行作业

  • 我想知道下次处理这类工作的更好方法


只要执行这些脚本,Linux就会在内部将这些任务正确地分配给可用的CPU。这取决于Linux任务调度程序。但是,如果需要,也可以使用
任务集
(请参阅
人工任务集
)在特定CPU上执行任务。您可以通过脚本执行30K任务。请记住,以这种手动方式,确保您正在做的事情。

我使用了
REDIS
来做这类事情-它安装非常简单,CLI也很容易使用

我主要使用
LPUSH
将所有作业推送到REDIS中的“队列”上,并使用
BLPOP
从队列中执行作业的阻塞移除。因此,您可以在开始时执行
LPUSH
30000个作业(或脚本名称或参数),然后在后台启动40个进程(每个CPU 1个),每个进程将在循环中执行
BLPOP
以获取作业,运行它并执行下一个

您可以添加复杂的层次,将已完成的作业记录在另一个“队列”中

这里有一个小演示,演示如何做

首先,在网络中的任何计算机上启动Redis服务器:

./redis-server &    # start REDIS server in background
或者,如果您总是使用它,您可以将其放在系统启动中

现在将3个作业推送到称为作业的队列中:

./redis-cli         # start REDIS command line interface
redis 127.0.0.1:6379> lpush jobs "job1"
(integer) 1
redis 127.0.0.1:6379> lpush jobs "job2"
(integer) 2
redis 127.0.0.1:6379> lpush jobs "job3"
(integer) 3
查看队列中有多少作业:

redis 127.0.0.1:6379> llen jobs
(integer) 3
redis 127.0.0.1:6379> brpop jobs 0
for ((i=0;i<30000;i++)) ; do
    echo "lpush jobs job$i" | redis-cli
done
以无限超时等待作业

redis 127.0.0.1:6379> brpop jobs 0
1) "jobs"
2) "job1"
redis 127.0.0.1:6379> brpop jobs 0
1) "jobs"
2) "job2"
redis 127.0.0.1:6379> brpop jobs 0
1) "jobs"
2) "job3"
最后一个将等待很长时间,因为队列中没有作业:

redis 127.0.0.1:6379> llen jobs
(integer) 3
redis 127.0.0.1:6379> brpop jobs 0
for ((i=0;i<30000;i++)) ; do
    echo "lpush jobs job$i" | redis-cli
done
当然,这很容易编写脚本:

将30000个作业放入队列:

redis 127.0.0.1:6379> llen jobs
(integer) 3
redis 127.0.0.1:6379> brpop jobs 0
for ((i=0;i<30000;i++)) ; do
    echo "lpush jobs job$i" | redis-cli
done
或者更简单地说:

redis-cli llen jobs
(integer) 30000
你可以开始40份这样的工作:

#!/bin/bash
for ((i=0;i<40;i++)) ; do
    ./Keep1ProcessorBusy  $i &
done
#!/bin/bash

# Endless loop picking up jobs and processing them
while :
do
    job=$(echo brpop jobs 0 | redis_cli)
    # Set processor affinity here too if you want to force it, use $1 parameter we were called with
    do $job
done
当然,您想要运行的实际脚本或作业也可以存储在Redis中



作为一个完全不同的选项,您可以查看
gnupallel
,它是。还请记住,您可以使用
-P
选项通过
xargs
运行
find
的输出来并行化内容。

正如Mark Setchell所说:GNU并行

find scripts/ -type f | parallel
如果您坚持让8个CPU保持空闲:

find scripts/ -type f | parallel -j-8
但通常使用
nice
更为有效,因为当没有其他人需要时,这将为您提供全部48个内核:

find scripts/ -type f | nice -n 15 parallel
要了解更多信息:

  • 观看简介视频,快速介绍:
  • 浏览教程(man parallel_教程)。您可以使用命令行 带着对你的爱

编写一个脚本,其任务是通过分叉多达40个进程来分发30000个作业。此父脚本将等待子进程完成,然后通过分叉新进程转到下一个作业。在任何时候,您最多可以有40个子进程。您现在有40个文件夹保存每个作业的“文件”,对吗?为什么不使用一个名为“queue/”的文件夹来保存所有文件,而运行作业的脚本将“将一个文件从文件夹队列/移动到文件夹工作/并执行此作业;完成后,将文件移动到文件夹完成/”?这样,您启动的脚本数=并发数;您可以查看队列中的内容、工作情况和完成情况。当您需要重新启动时,只需将所有文件移回“queue/”文件夹。您还可以在处理过程中删除更多的作业,或者删除尚未启动的作业。注意:在您的作业处理脚本中,当文件移动时,最好将它移到文件夹“工作/”中,将其PID($$)附加在文件名中,并检查移动文件是否真的保存了它的PID(文件名)。这是一种处理锁定的简单方法,因为文件系统将以原子方式“移动”文件,不需要信号量或锁定。@KenCheung forking是实现您的建议所必需的。哦。。。对事实上,我有一些类似的东西,我让我的脚本开始使用/etc/inittab(CentOS 5),当队列/文件夹中没有文件时,它就会休眠。我假设这个问题意味着他不希望所有30K作业同时运行。使用taskset分配处理器关联并不意味着作业将逐个执行。它们将一起运行,就像我们在Linux上只有一个CPU(核心)的那一天——多任务。taskset将一个特定的任务关联到一个特定的CPU,我的意思是将所有这些任务关联到可用的CPU,并以循环方式安排它们,我也警告过他这一点。我只是告诉他他可以选择,我没有坚持。我不认为这对工作有什么用处。@aravindramesh你不理解。让我试试,无论你何时运行脚本,这都是一个新的过程。Linux任务调度器负责决定您的任务将如何获得cpu,即任务调度器上的哪个任务将获得哪个cpu,调度器还包含负载平衡器,它确保没有cpu保持空闲,每当cpu空闲时,它就会从其他繁忙的cpu中提取任务,这样Linux就提供了最佳吞吐量。现在,如果你想一次将它们分成40个任务,你可以这样做,但这不是严格要求的。但是,如果你真的想要它,那么你可以借助taskset。希望你得到它,但它会只提供48个作业,还是会提交所有30K作业?它会在所有30K作业完成之前,每个cpu核心运行1个作业。如果您还有更多问题,我建议您先观看介绍视频并浏览教程:它将解决大多数问题。任何有关Redis的教程都将非常有用。我用一个非常具体的示例更新了我的答案,可能会帮助您了解它有多简单。+1用于向我展示各种选项。我正在使用并行的工作。谢谢你