将 xargs 用于并行 Python 脚本
Using xargs for parallel Python scripts
我目前有一个 bash 脚本,script.sh,有两个嵌套循环。第一个枚举a的可能值,第二个枚举b的可能值,比如
#!/bin/sh
for a in {1..10}
do
for b in {1..10}
do
nohup python script.py $a $b &
done
done
所以这会产生 100 个 Python 进程 运行 script.py,每个 (a,b) 对一个。但是,我的机器只有 5 个内核,所以我想将进程数限制在 5 个,以避免 thrashing/wasteful 切换。目标是我总是 运行 5 个进程,直到完成所有 100 个进程。
xargs 似乎是一种方法,但我不知道如何将这些参数传递给 xargs。我已经检查了其他类似的问题,但对周围的 bash 行话的理解不够好,无法知道发生了什么。比如我试过
seq 1 | xargs -i --max-procs=5 bash script.sh
但这似乎没有任何作用 - script.sh 像以前一样运行并且仍然产生 100 个进程。
我想我误解了 xargs 的工作原理。
谢谢!
这实际上看起来更像:
#!/bin/bash
for a in {1..10}; do
for b in {1..10}; do
printf '%s[=10=]' "$a" "$b"
done
done | xargs -0 -x -n 2 -P 5 python script.py
请注意,没有 nohup
,也没有 &
——要跟踪并发调用的数量,xargs
需要直接执行 Python 脚本,并且该过程在完成之前无法退出。
非标准(但广泛可用)-0
扩展要求输入采用 NUL 分隔形式(如使用 printf '%s[=15=]'
创建的);这确保了带有空格、引号、反斜杠等的参数的正确行为。
同样非标准的 -P 5
设置最大进程数(在某种程度上比 --max-procs=5
更便携,GNU 支持但现代 BSD xargs 不支持)。
-n 2
表示 Python 脚本的每个实例仅接收两个参数,因此每对输入开始一个。
-x
(与-n 2
结合使用)表示如果单个Python实例不能被赋予两个参数(例如,如果参数太长两者都不能放在一个命令行上),这应该被视为失败,而不是仅使用一个参数调用 Python 实例。
如果您使用 bash,那么以下应该有效:
#!/bin/bash
for a in {1..10}
do
for b in {1..10}
do
if [ `jobs | wc -l` -lt 6 ]; then # less than 6 background jobs
nohup python script.py $a $b &
else
wait -n # wait for any background job to terminate
fi
done
done
GNU Parallel 正是为这些类型的工作而设计的:
parallel python script.py ::: {1..10} ::: {1..10}
如果您需要以不同方式放置 $a 和 $b,您可以使用 {1} 和 {2} 来引用两个输入源:
parallel python script.py --option-a {1} --option-b {2} ::: {1..10} ::: {1..10}
GNU Parallel 是一个通用的并行化器,可以很容易地在同一台机器或您可以通过 ssh 访问的多台机器上并行 运行 作业。它通常可以替代 for
循环。
如果您有 32 个不同的作业要 运行 在 4 CPU 秒内执行,一个直接的并行化方法是 运行 每个 CPU 8 个作业:
GNU Parallel 在一个进程完成时生成一个新进程 - 保持 CPU 处于活动状态,从而节省时间:
安装
如果 GNU Parallel 未打包用于您的发行版,您可以进行个人安装,这不需要 root 访问权限。这样做可以在 10 秒内完成:
(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash
有关其他安装选项,请参阅 http://git.savannah.gnu.org/cgit/parallel.git/tree/README
了解更多
查看更多示例:http://www.gnu.org/software/parallel/man.html
观看介绍视频:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
完成教程:http://www.gnu.org/software/parallel/parallel_tutorial.html
注册电子邮件列表以获得支持:https://lists.gnu.org/mailman/listinfo/parallel
我目前有一个 bash 脚本,script.sh,有两个嵌套循环。第一个枚举a的可能值,第二个枚举b的可能值,比如
#!/bin/sh
for a in {1..10}
do
for b in {1..10}
do
nohup python script.py $a $b &
done
done
所以这会产生 100 个 Python 进程 运行 script.py,每个 (a,b) 对一个。但是,我的机器只有 5 个内核,所以我想将进程数限制在 5 个,以避免 thrashing/wasteful 切换。目标是我总是 运行 5 个进程,直到完成所有 100 个进程。
xargs 似乎是一种方法,但我不知道如何将这些参数传递给 xargs。我已经检查了其他类似的问题,但对周围的 bash 行话的理解不够好,无法知道发生了什么。比如我试过
seq 1 | xargs -i --max-procs=5 bash script.sh
但这似乎没有任何作用 - script.sh 像以前一样运行并且仍然产生 100 个进程。
我想我误解了 xargs 的工作原理。
谢谢!
这实际上看起来更像:
#!/bin/bash
for a in {1..10}; do
for b in {1..10}; do
printf '%s[=10=]' "$a" "$b"
done
done | xargs -0 -x -n 2 -P 5 python script.py
请注意,没有 nohup
,也没有 &
——要跟踪并发调用的数量,xargs
需要直接执行 Python 脚本,并且该过程在完成之前无法退出。
非标准(但广泛可用)-0
扩展要求输入采用 NUL 分隔形式(如使用 printf '%s[=15=]'
创建的);这确保了带有空格、引号、反斜杠等的参数的正确行为。
同样非标准的 -P 5
设置最大进程数(在某种程度上比 --max-procs=5
更便携,GNU 支持但现代 BSD xargs 不支持)。
-n 2
表示 Python 脚本的每个实例仅接收两个参数,因此每对输入开始一个。
-x
(与-n 2
结合使用)表示如果单个Python实例不能被赋予两个参数(例如,如果参数太长两者都不能放在一个命令行上),这应该被视为失败,而不是仅使用一个参数调用 Python 实例。
如果您使用 bash,那么以下应该有效:
#!/bin/bash
for a in {1..10}
do
for b in {1..10}
do
if [ `jobs | wc -l` -lt 6 ]; then # less than 6 background jobs
nohup python script.py $a $b &
else
wait -n # wait for any background job to terminate
fi
done
done
GNU Parallel 正是为这些类型的工作而设计的:
parallel python script.py ::: {1..10} ::: {1..10}
如果您需要以不同方式放置 $a 和 $b,您可以使用 {1} 和 {2} 来引用两个输入源:
parallel python script.py --option-a {1} --option-b {2} ::: {1..10} ::: {1..10}
GNU Parallel 是一个通用的并行化器,可以很容易地在同一台机器或您可以通过 ssh 访问的多台机器上并行 运行 作业。它通常可以替代 for
循环。
如果您有 32 个不同的作业要 运行 在 4 CPU 秒内执行,一个直接的并行化方法是 运行 每个 CPU 8 个作业:
GNU Parallel 在一个进程完成时生成一个新进程 - 保持 CPU 处于活动状态,从而节省时间:
安装
如果 GNU Parallel 未打包用于您的发行版,您可以进行个人安装,这不需要 root 访问权限。这样做可以在 10 秒内完成:
(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash
有关其他安装选项,请参阅 http://git.savannah.gnu.org/cgit/parallel.git/tree/README
了解更多
查看更多示例:http://www.gnu.org/software/parallel/man.html
观看介绍视频:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
完成教程:http://www.gnu.org/software/parallel/parallel_tutorial.html
注册电子邮件列表以获得支持:https://lists.gnu.org/mailman/listinfo/parallel