Linux 并行运行shell脚本
我有一个shell脚本Linux 并行运行shell脚本,linux,bash,shell,unix,parallel-processing,Linux,Bash,Shell,Unix,Parallel Processing,我有一个shell脚本 洗牌大文本文件(600万行6列) 根据第一列对文件进行排序 输出1000个文件 所以伪代码看起来像这样 file1.sh #!/bin/bash for i in $(seq 1 1000) do Generating random numbers here , sorting and outputting to file$i.txt done 有没有办法以并行运行此shell脚本来充分利用多核CPU 目前,./file1.sh以1到1000次的顺序执
file1.sh
#!/bin/bash
for i in $(seq 1 1000)
do
Generating random numbers here , sorting and outputting to file$i.txt
done
有没有办法以并行运行此shell脚本来充分利用多核CPU
目前,./file1.sh
以1到1000次的顺序执行,速度非常慢
感谢您的帮助。要使事情并行运行,请在shell命令末尾使用“&”在后台运行,然后默认情况下,wait
将等待所有后台进程完成。所以,也许并行启动10个,然后等待,然后再执行另一个10个。您可以使用两个嵌套循环轻松完成此操作。请检查,这些循环可用于并行运行脚本的部分
我尚未对此进行测试,但这可能是一个开始:
#!/bin/bash
for i in $(seq 1 1000)
do
( Generating random numbers here , sorting and outputting to file$i.txt ) &
if (( $i % 10 == 0 )); then wait; fi # Limit to 10 concurrent subshells.
done
wait
另一个非常方便的方法是使用,如果您还没有安装,那么它非常值得安装;如果任务不一定需要相同的时间,这是非常宝贵的
seq 1000 | parallel -j 8 --workdir $PWD ./myrun {}
将启动/myrun 1
,/myrun 2
等,确保一次运行8个作业。如果您想同时在多个节点上运行,它还可以获取节点列表,例如在PBS作业中;我们向用户提供的关于如何在系统上执行此操作的说明如下
更新为添加:您希望确保您使用的是gnu并行,而不是moreutils包中提供的更有限的同名实用程序(描述了两者的不同历史)。有一个简单的可移植程序可以为您做到这一点:。PPSS会自动为您安排作业,方法是检查有多少内核可用,并在每次另一个作业刚刚完成时启动另一个作业。在GNU parallel的文档中,有一个可以从shell并行运行作业的工具,它甚至包括作业之间的比较。有很多很多解决方案。另一个好消息是,它们在调度作业方面可能非常有效,因此所有的内核/处理器都会一直处于忙碌状态。生成随机数很容易。
假设你有一个像商店数据库这样的大文件,你想在某个特定的基础上重写这个文件。
我的想法是计算内核的数量,将文件拆分为多少个内核,生成一个script.cfg文件,split.sh和recombine.sh
split.sh将文件拆分为多少个内核,clone script.cfg(用于更改这些巨大文件中的内容的脚本),clone script.cgf将文件拆分为多少个内核,使其可执行,在克隆中搜索并替换一些变量,这些变量必须知道文件要处理的部分
并在后台运行它们
克隆完成时,生成一个克隆$core.ok文件,因此,当所有克隆完成时,只有在生成所有.ok文件时,才会通知循环将部分结果重新组合为单个结果。
可以用“等等”来完成,但我喜欢我的方式
看看底部,部分翻译为英语
通过这种方式,我可以在2分钟内处理20000篇包含16列的文章(四核),而不是8列(单核)
您必须关心CPU温度,因为所有内核都以100%的空闲率运行
IDLE_CPU=1
NCPU=$(nproc)
int_childs() {
trap - INT
while IFS=$'\n' read -r pid; do
kill -s SIGINT -$pid
done < <(jobs -p -r)
kill -s SIGINT -$$
}
# cmds is array that hold commands
# the complex thing is display which will handle all cmd output
# and serialized it correctly
trap int_childs INT
{
exec 2>&1
set -m
if [ $NCPU -gt $IDLE_CPU ]; then
for cmd in "${cmds[@]}"; do
$cmd &
while [ $(jobs -pr |wc -l) -ge $((NCPU - IDLE_CPU)) ]; do
wait -n
done
done
wait
else
for cmd in "${cmds[@]}"; do
$cmd
done
fi
} | display
NCPU=$(nproc)
int_childs(){
陷阱整数
而IFS=$'\n'读取-r pid;执行
kill-s SIGINT-$pid
完成<&1
set-m
如果[$NCPU-gt$IDLE_CPU];则
对于“${cmds[@]}”中的cmd,请执行以下操作
$cmd&
而[$(jobs-pr | wc-l)-ge$((NCPU-IDLE_CPU))];do
等等
完成
完成
等待
其他的
对于“${cmds[@]}”中的cmd,请执行以下操作
$cmd
完成
fi
}|显示
您可能想看看runp
是一个简单的命令行工具,可以并行运行(shell)命令。当您希望同时运行多个命令以节省时间时,它非常有用。它很容易安装,因为它是一个二进制文件。它已经在Linux(amd64和arm)和MacOS/darwin(amd64)上进行了测试。如果您发现自己需要在shell脚本中编写任何非琐碎的东西(例如,多处理等),那么是时候用适当的编程语言重新编写它了。这将并行启动所有千项任务,这可能会导致太多的交换/争用,以获得最佳的工作吞吐量,但这肯定是一种合理且简单的开始方式。这一点很好!最简单的解决方案是使用一个外部循环来限制已启动的子shell的数量,并在它们之间等待。@Anders:或者在上面的循环中的“完成”之前插入一个“if($i%10==0));然后等待;fi…@Tony:我认为将其保留在其中是有意义的<代码>等待没有运行子shell似乎没有任何作用,如果选择的并发子shell数量不是要运行的任务数量的一个因素,我们可能会在循环结束时得到仍在运行的活动子shell。如果所有作业占用完全相同的时间,此解决方案效果最佳。如果这些作业占用的时间不相同,您将浪费CPU时间等待其中一个长作业完成。换言之:它不会一直保持10个作业同时运行。非常感谢您的建议。所有CPU现在都在工作。你知道如何让它在节点间运行吗?我正在使用PBS将作业提交给高性能计算,节点数为2:ppn=8,但只有一个节点在工作。@Tony:直到现在我才听说PBS。。。听起来很有趣,但我不知道如何使用它。很抱歉有关PBS问题和跨节点的问题,请参阅。等待是如何工作的?你能用一个例子更新你的答案吗?我想在某个函数中运行几个线程,但在所有线程完成之前,下一个函数不能启动。@d-bwait
等待后台进程完成,而不是线程。例如,用于文件在magnage.txt massible.log magnific.xml中;是否创建scp$文件someuser@somehost:/tmp/&;完成;等待echo“完成”
将运行三个scp
(安全公司