我经常发现自己编写简单的for循环来对许多文件执行操作,例如:
for i in `find . | grep ".xml$"`; do bzip2 $i; done
似乎有点令人沮丧的是,在我的4核机器上只使用了一个核心..有一种简单的方法可以为我的shell脚本添加并行性吗?
编辑:为我的问题介绍更多的背景,对不起,我开始时并不是更清楚!
我经常想在合理大小的数据集(通常在100到10,000之间)上运行简单(ish)脚本,例如绘制图形,压缩或解压缩,或运行某些程序。我用来解决这些问题的脚本看起来像上面那样,但可能有不同的命令,甚至是一系列要执行的命令。
例如,刚才我正在运行:
for i in `find . | grep ".xml.bz2$"`; do find_graph -build_graph $i.graph $i; done
所以我的问题绝不是特定于bzip的! (虽然并行bzip确实看起来很酷,但我打算将来使用它。)
答案 0 :(得分:14)
解决方案:使用xargs
并行运行(不要忘记-n
选项!)
find -name \*.xml -print0 | xargs -0 -n 1 -P 3 bzip2
答案 1 :(得分:6)
This perl program可以很好地满足您的需求,您只需这样做:
runN -n 4 bzip2 `find . | grep ".xml$"`
答案 2 :(得分:4)
gnu make有一个很好的并行功能(例如-j 5)可以在你的情况下工作。创建一个Makefile
%.xml.bz2 : %.xml
all: $(patsubt %.xml,%xml.bz2,$(shell find . -name '*.xml') )
然后做一个
nice make -j 5
用一些数字替换'5',可能比CPU的数量多1。您可能希望做到“好”,以防万一其他人想要在您使用机器时使用该机器。
答案 3 :(得分:2)
一般问题的答案很难,因为它取决于您要并行化的事物的细节。 另一方面,为了这个特定的目的,你应该使用pbzip2而不是普通的bzip2(可能已经安装了pbzip2或者至少在存储库或你的发行版中)。有关详细信息,请参阅此处:http://compression.ca/pbzip2/
答案 4 :(得分:2)
我发现这种操作适得其反。原因是在读/写时间越长的同时访问磁盘的进程越多,因此最终结果会在更长的时间内结束。无论你有多少核心,这里的瓶颈都不会是CPU问题。
你有没有在同一台高清硬盘上同时执行过两个简单的大文件副本?我通常会更快地复制一个而不是另一个。
我知道这个任务涉及一些CPU功率(bzip2要求压缩方法),但是在走向“挑战”路径之前尝试测量第一个CPU负载,我们所有技术人员往往选择的频率远远超过需要。
答案 5 :(得分:2)
我为bash做了类似的事情。对于一次性,并行make技巧可能要快很多,但是这里是在bash中实现这样的东西的主要代码部分,你需要为你的目的修改它:
#!/bin/bash
# Replace NNN with the number of loops you want to run through
# and CMD with the command you want to parallel-ize.
set -m
nodes=`grep processor /proc/cpuinfo | wc -l`
job=($(yes 0 | head -n $nodes | tr '\n' ' '))
isin()
{
local v=$1
shift 1
while (( $# > 0 ))
do
if [ $v = $1 ]; then return 0; fi
shift 1
done
return 1
}
dowait()
{
while true
do
nj=( $(jobs -p) )
if (( ${#nj[@]} < nodes ))
then
for (( o=0; o<nodes; o++ ))
do
if ! isin ${job[$o]} ${nj[*]}; then let job[o]=0; fi
done
return;
fi
sleep 1
done
}
let x=0
while (( x < NNN ))
do
for (( o=0; o<nodes; o++ ))
do
if (( job[o] == 0 )); then break; fi
done
if (( o == nodes )); then
dowait;
continue;
fi
CMD &
let job[o]=$!
let x++
done
wait
答案 6 :(得分:1)
我认为你可以到以下
for i in `find . | grep ".xml$"`; do bzip2 $i&; done
但是,由于你立即拥有文件,这会分散许多进程,而不是一次只运行四个进程。
答案 7 :(得分:1)
如果你今天必须解决问题,你可能会使用像GNU Parallel这样的工具(除非你的任务有专门的并行工具,如pbzip2
):
find . | grep ".xml$" | parallel bzip2
了解更多信息: