Jerkwin分享 http://blog.sciencenet.cn/u/Jerkwin

博文

Bash脚本实现批量作业并行化

已有 16041 次阅读 2013-12-16 03:27 |个人分类:我的工具箱|系统分类:科研笔记| Shell, 并行, bash, 命名管道

Bash脚本实现批量作业并行化
2013-12-14 21:26:02

Linux下运行作业时, 经常会遇到以下情形: 有大量作业需要运行, 完成每个作业所需要的时间也不是很长. 如果我们以串行方式来运行这些作业, 可能要耗费较长的时间; 若采用并行方式运行则可以大大节约运行时间. 再者, 目前的计算机绝大部分都是多核架构, 要想充分发挥它们的计算能力也需要并行化. 总结网上看到的资料, 利用Bash脚本, 可以采用下面几种方法实现批量作业的并行化. 注意, 下面论述中将不会区分进程和线程, 也不会区分并行和并发.

1. 采用GNUparalle程序

parallelGNU专门用于并行化的一个程序, 对于简单的批量作业并行化非常合适. 使用parallel不需要编写脚本, 只需在原命令的基础上简单地加上parallel就可以了. 所以, 如果能用paralle并行化你的作业, 请优先使用. 有关paralle的详细说明, 请参考其官方文档.

2. 最简单的并行化方法:&+wait

利用Bash的后台运行&wait函数, 可实现最简单的批量作业并行化.

如下面的代码, 串行执行大约需要10

改为下面的简单并行代码理想情况下可将运行时间压缩到3秒左右

3. 进程数可控的并行化方法(1): 模拟队列

使用Bash脚本同时运行多个进程并无困难, 主要存在的问题是如何控制同时运行的进程数目. 上面的简单并行化方法使用时进程数无法控制, 因而功能有限, 因为大多数时候我们需要运行的作业数远远超过可用处理器数, 这种情况下若大量作业同时在后台运行, 会导致运行速度变慢, 并行效率大大下降. 一种简单的解决方案就是模拟一个限定最大进程数的队列, 以进程PID做为队列元素, 每隔一定时间检查队列, 若队列中有作业完成, 则添加新的作业到队列中. 这种方法还可以避免由于不同作业耗时不同而产生的无用等待. 下面是根据网上的代码改写的一种实现. 实用性更强的代码, 参考原文.

一个更简洁的方法是记录PID到数组, 通过检查PID存在与否以确定作业是否运行完毕. 可实现如下

3. 进程数可控的并行化方法(2): 命名管道

上面的并行化方法也可利用命名管道来实现, 命名管道是Linux下进程间进行通讯的一种方法, 也称为先入先出(fifo,first in first out)文件. 具体方法是创建一个fifo文件, 作为进程池, 里面存放一定数目的"令牌".作业运行规则如下: 所有作业排队依次领取令牌; 每个作业运行前从进程池中领取一块令牌, 完成后再归还令牌; 当进程池中没有令牌时, 要运行的作业只能等待. 这样就能保证同时运行的作业数等于令牌数. 前面的模拟队列方法实际就是以PID作为令牌的实现.

据我已查看的资料, 这种方法在网络上讨论最多. 实现也很简洁, 但理解其代码需要的Linux知识较多. 下面是我改写的示例代码及其注释.

注意:

(1) exec6<>$Pfifo 这一句很重要, 若无此语句, $Pfifo写入数据时, 程序会被阻塞, 直到有read读出了文件中的数据为止. 而执行了此语句, 就可以在程序运行期间不断向文件写入数据而不会阻塞, 并且数据会被保存下来以供read读出.

(2) $Pfifo中已经没有数据时,read无法读到数据, 进程会被阻塞在read操作上, 直到有子进程运行结束,向$Pfifo写入一行.

(3) 核心执行部分也可使用如下方式

{}()的区别在shell是否会衍生子进程

(4) 此方法在目前的Cygwin(版本1.7.27)下无法使用, 因其不支持双向命名管道. 有人提到一个解决方案, 使用两个文件描述符来替代单个文件描述符, 但此方法我没有测试成功.


参考资料:

1. 简洁的模拟队列方法实现
shell
里如何实现"多线程"?
http://blog.linuxeden.com/html/55/t-164155.html

2. 模拟队列方法, 实用性更强的代码
A srcipt for running processes in parallel in Bash
http://pebblesinthesand.wordpress.com/2008/05/22/a-srcipt-for-running-processes-in-parallel-in-bash/

3. 命名管道方法及其解释
bash
实现"多进程"
http://www.cnitblog.com/sysop/archive/2008/11/03/50974.aspx

SHELL模拟多线程脚本的详细注解
http://findingcc.blog.51cto.com/1045158/287417

一段相当精彩的shell脚本(模拟多线程)
http://www.blogbus.com/luobeng-logs/123290553.html

Linux下模拟多线程的并发并发shell脚本
http://www.centoscn.com/shell/2013/0731/823.html

shell脚本模拟多进程
http://www.phpfans.net/article/htmls/201009/MzA3ODEy.html

shell并发脚本学习
http://raocl.wordpress.com/tag/mkfifo/

4. Cygwin下双向命名管道的问题
bi-directional named pipe
http://cygwin.com/ml/cygwin/2009-07/msg00081.html



https://blog.sciencenet.cn/blog-548663-750136.html

上一篇:常见冰的晶体结构及其cif文件
下一篇:Drude振子的相互作用能
收藏 IP: 72.204.51.*| 热度|

2 许优华 李琼玲

该博文允许注册用户评论 请点击登录 评论 (1 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-12-22 11:00

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部