一种基于类UNIX系统进行高效并行执行的方法
本文介绍一种利用GNU parallel进行高并发运行计算密集型并行任务的方案。上次用这软件是在写爬虫批量下载漫画…没想到科研中也遇到了类似的问题。遂记录下来与大家分享。
系统要求
首先,Windows系统是不可以的。从官网上看,GNU parallel没有win32 build。或者,我正在找替代或者解决方案。
已知的尝试是在git-bash里安装parallel,但是安装是能安装,却不能正常工作。在git-bash里安装parallel参考了stackoverflow的一篇回答。
我在git-bash里运行了以下指令成功安装parallel,虽然安装过程中不停地报错。
1 | $ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \ |
问题描述
本文将要处理的问题具有图1所示结构,即某一个步骤完全由有限个并行执行的任务组成。这些并行任务之间并没有任何依赖关系,但下一步依赖于所有这些任务,即当这些并行任务都结束时,下一项任务才能开始。
以下载一话漫画为例。
假设某连载漫画的第5话有20页图片,在某漫画网站上,该漫画信息页面的路径为/comic/:comic_id,获取一张图片的路径为/gallery/:gallery_id/:pic_file,其中:pic_file是以.png或者.jpg结尾的图片名。
在漫画信息页面上显示有comic_id和gallery_id的对应关系,每一个comic_id有且仅有一个gallery_id与之对应。 :pic_file的列表和次序可以通过带有:gallery_id请求某API获取。
好吧,这些都不重要,不要乱爬漫画站。
解决方案
可以看到,上述任务可以使用图1所示结构来描述,获取comic_id和gallery_id以及:pic_file列表可以看作是并行任务集合的前置准备。所有图片的下载可以是高并发的,彼此之间并没有什么依赖关系。任务完成时所有图片都已经下载完毕。
那么,如何使用GNU parallel写出最快速的漫画爬虫呢? shell脚本的部分内容如下:
1 | # comic_id := user defined number |
其中,:::非常有特点,既不是一个:也不是两个:。
-j选项指定使用多少个CPU核心参与并行任务的执行,未指定则默认全部(物理核数)。 download_pic为要并行执行的任务,:::后边是任务参数。
当有多个:::时会自动枚举全部选项,比如,parallel echo ::: 1 2 ::: a b c的一种可能的输出结果为:
1 | $ parallel echo ::: 1 2 ::: a b c |
P.S. 为了最高的效率,parallel不会很及时地进行输出,而是先缓存起来。因此命令行或者文件输出和任务执行情况不同步。
注意事项
正如系统要求中parallel的输出中所提到的,当论文数据处理用到了该工具的时候,应该按照parallel的作者给出的形式[1]进行引用。
1 | $ parallel --citation |
Fin.