How to Improve Performance Your Cmd by Parallel
有很多时候,处理一个大文件,常规命令并不能很好的利用多核
例如,一个1T的文本,百亿条数据,我想要:
1 |
wc -l test.txt |
---|
或者
1 |
fgrep xxxx test.txt |
---|
一般机器就会自觉进入一核有难,其它核点赞
的看戏模式。
我花钱配了这么多核,加了这么多内存,不是让大家来看戏的。于是祭出parallel
~
原理
parallel 是一个perl脚本,通过分割输入,并行处理的方式来加速执行命令。
例如:
1 |
wc -l test.txt |
---|
简单想想就是用个for循环split文件,挨个wc,然后相加。parallel就是自动帮你把这类事情做掉而已。大道不过两三行,所谓外部排序,Map-Reduce莫不如是。
安装 (ubuntu 16.04LTS)
1 |
apt-get install parallel |
---|
示例
最快的办法计算一个大文件的行数
1 |
cat bigfile.txt | parallel --no-notice --pipe wc -l | awk '{s+=$1} END {print s}' |
---|
非常的巧妙,先使用parallel命令‘mapping’出大量的wc -l调用,形成子计算,最后通过管道发送给awk进行汇总
SED, 想在一个巨大的文件里使用sed命令做大量的替换操作吗?
常规做法:
1 |
sed s^old^new^g bigfile.txt |
---|
现在你可以:
1 |
cat bigfile.txt | parallel --no-notice --pipe sed s^old^new^g |
---|
GREP 一个非常大的文本文件
以前你可能会这样:
1 |
grep pattern bigfile.txt |
---|
现在你可以这样:
1 |
cat bigfile.txt | parallel --no-notice --pipe grep 'pattern' |
---|
或者这样:
1 |
cat bigfile.txt | parallel --no-notice --block 10M --pipe grep 'pattern' |
---|
这第二种用法使用了 –block 10M参数,这是说每个内核处理1千万行——你可以用这个参数来调整每个CUP内核处理多少行数据。
压缩一个非常大的文件
bzip2是比gzip更好的压缩工具,但它很慢!别折腾了,我们有办法解决这问题。
以前的做法:
1 |
cat bigfile.bin | bzip2 --best > compressedfile.bz2 |
---|
现在这样:
1 |
cat bigfile.bin | parallel --no-notice --pipe --recend '' -k bzip2 --best > compressedfile.bz2 |
---|
扩展
作为一个Python党,经常写一些用过即弃
的边角料脚本
比如最近要把一个1T的文件汉字全部转换为拼音,初版当然是这样的:
版本1
1 2 3 |
with io.open(sys.argv[1], encoding='utf-8') as fp: for line in fp: print(lazy_pinyin(line)) |
---|
lazy_pinyin的效率奇慢无比,这回陷入了一核有难,其它核+内存+磁盘全部看戏模式
作为一个初级合格的Python开发人员,你当然说要用process,于是我们有了第二版:
版本2
1 2 3 4 5 6 |
from multiprocessing import Pool pool = Pool(16) with io.open(sys.argv[1], encoding='utf-8') as fp: pool.map(lazy_pinyin, fp, 16) pool.close() pool.join() |
---|
嗯,很好,16个核都跑起来了;但是你有很快尴尬的发现,map把文件一把load进来,内存有难了
~~~~
作为一个初级合格的Python开发人员,你当然说不要一把读进来,要用chunk_read,一次读一块,或者更高级一点,直接用mmap映射进内存巴拉巴拉
少年,这还是那个边角料脚本吗,你已经在它上面操心一个小时了,还能不能愉快的玩耍了
让 parallel来拯救你
版本3
1 2 3 4 5 |
import fileinput if __name__ == '__main__': for line in fileinput.input(): lazy_pinyin(line) |
---|
然后执行:
1 |
cat bigfile.txt| parallel --no-notice --pipe python pinyinconv.py > pinyin.result |
---|
享受所有CPU满负荷运载的工头压榨工人的快感吧
一些扩展
- 为啥所有的parallel都带有一个奇怪的—no-notice?
嗯,虽然这个作者非常非常好,但是他总是在命令前面输出一些慈善提示;当然我并不是讨厌这种做法,但看多了总有些疲劳,你懂的~~
- 我有一些参数想传给程序,怎么办?
1 |
seq 3|parallel --no-notice -q echo seq{} |
---|
- 这个命令很好,但是语法好像啰嗦了一些,还有其它的替代命令吗?
嗯~ o( ̄▽ ̄)o,还是有的,xargs有个-n参数,类似的效果,不过功能弱化很多,基本上是鸡肋
参考:
手册:
https://www.gnu.org/software/parallel/parallel_tutorial.html
资料:
http://www.freeoa.net/osuport/sysadmin/use-gnu-parallel-multi-core-speed-up-cmd_2343.html
我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1bnzu1pmog27t
- 【专知-Deeplearning4j深度学习教程03】使用多层神经网络分类MNIST数据集:图文+代码
- TypeScript 1.6发布:完全支持React/JSX
- 【专知-Java Deeplearning4j深度学习教程04】使用CNN进行文本分类:图文+代码
- sql server之数据库语句优化
- 【专知-Java Deeplearning4j深度学习教程05】无监督特征提取神器—AutoEncoder:图文+代码
- 平衡树初阶——AVL平衡二叉查找树+三大平衡树(Treap + Splay + SBT)模板【超详解】
- HDU 2689 Sort it【树状数组】
- BZOJ 1800: [Ahoi2009]fly 飞行棋【思维题,n^4大暴力】
- Vijos P1066 弱弱的战壕【多解,线段树,暴力,树状数组】
- GeetTest~下一代验证(附C#案例)
- [接口测试 - http.client篇] 17 http.client之入门级接口测试框架
- 评论JS插件~多说+畅言
- jQuery HTML5 Uploader
- 1022: [SHOI2008]小约翰的游戏John【Nim博弈,新生必做的水题】
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法