Shell 利用并行进程加速命令执行,计算能力的持续攀升不仅仅是因为处理器有了更高的时钟频率,还因为多核的出现。这意味着单个物理处理器中包含了多个逻辑处理器。这就像是有了多台计算机一样。
但除非软件能够善加利用多核,否则它们毫无用武之地。例如,一个需要进行大量运算的程序可能仅运行在其中一个核心上,而其他的核心都处于闲置状态。如果想提高速度,软件必须留意并充分利用多核。本章我们会看到如何让命令运行得更快。
实战演练
以之前讲过的md5sum
命令为例。由于需要执行复杂的运算,md5sum
属于CPU密集型命令。如果多个文件需要生成校验和,我们可以使用下面的脚本来运行md5sum
的多个实例:
#/bin/bash
#文件名: generate_checksums.sh
PIDARRAY=()
for file in File1.iso File2.iso
do
md5sum file &
PIDARRAY+=("!")
done
wait ${PIDARRAY[@]}
运行脚本后,可以得到如下输出:
$ ./generate_checksums.sh
330dcb53f253acdf76431cecca0fefe7 File1.iso
bd1694a6fe6df12c3b8141dcffaf06e6 File2.iso
输出结果和下面命令的结果一样:
md5sum File1.iso File2.iso
但如果多个md5sum
命令同时运行,配合多核处理器,你就会更快地获得运行结果(可以使用time
命令来验证)。
工作原理
我们利用了Bash的操作符&
,它使得shell将命令置于后台并继续执行脚本。这意味着一旦循环结束,脚本就会退出,而md5sum
进程仍在后台运行。为了避免这种情况,我们使用$!
来获得进程的PID,在Bash中,$!
保存着最近一个后台进程的PID。我们将这些PID放入数组,然后使用wait
命令等待这些进程结束。
补充内容
对于少量任务,Bash的操作符&
效果很好。如果你有数以百计的文件要计算校验和,那么脚本就会生成上百个进程,这有可能会强迫系统执行换页操作(swapping),拖慢执行速度。
并非所有系统都会安装GNU parallel
命令,不过你仍可以使用软件包管理器来安装。该命令能够优化资源使用,避免系统超载。
parallel
命令从stdin
中读取文件列表,使用类似于find
命令的-exec
选项来处理这些文件。符号{}
代表被处理的文件,符号{.}
代表无后缀的文件名。
下面的命令使用了Imagemagick的convert
程序来为目录中的所有图像创建新的缩放版本:
ls *jpg | parallel convert {} -geometry 50x50 {.}Small.jpg