您的位置:首页 > 其它

如何利用GNU Parallel工具在单机上处理百万级数量规模的文件

2016-02-20 13:46 330 查看
进行数据处理的时候我们经常会遇到这样的情况:一个数据集由一大堆很小的文件组成,这些小文件格式相同,可能是系统的日志文件或者产自传感器等终端。如下图:1234567个文件的总和才20GB左右。



处理这样的数据集给我们带来了如下的问题:

1) 当数据分散在这些大量的独立的小文件的时候,分析很困难。

2) 这些文件的总和超出了单机内存的容量,无法一次性全部载入,处理起来效率很低。

3) 使用分布式框架如hadoop虽然不用担心文件总大小的问题,但是单个文件又太小,HDFS中文件都是以block(64M)的形式存储,实际上HDFS主要是为了流式的访问大文件而设计的,处理大量小文件时候的效率非常低。

所以,我们能不能在单机上将这百万级数量的文件拼接成一个大文件后再处理?

使用linux操作系统的人想必对cat命令相当熟悉,cat命令可以将多个文件拼接成一个文件,这样,似乎一下子就可以解决文件数太多数据太分散的问题了。所以,我们很自然就有了如下的尝试:

$ cat * >> out.txt


然而,结果却并非如我们所愿,居然报错了!

<pre name="code" class="plain">-bash: /bin/cat: Argument list too long



因为cat命令一次不能拼接这么多的文件,事实上,Unix操作系统都将这些命令的参数限制在了10000以内,显然这次超出了,所以报错。此路不通。

接着,我们就想到一个很傻瓜式的方法,但一定可以达到目的,就是遍历这所有的文件,一个个的进行拼接:

<pre name="code" class="plain">for f in *; do cat "$f" >>../transactions_cat/transactions.csv; done


这一次成功了,但是却花了近三个小时!

显然这也不是我们所能接受的解决方案。到这里主角就可以出场了,GNU Parallel。

GNU Parallel是一个shell工具,为了在一台或多台计算机上并行的执行计算任务,一个计算任务可以是一条shell命令或者一个以每一行做为输入的脚本程序。一个计算任务也可以是一个从管道读取的一条命令。GNU Parallel会把输入分块,然后通过管道并行的执行。

前面的方法虽然使用了大量的时间,但是在命令执行期间,cpu的使用率一直处于很低的水平,因为那是完全序列化的操作。这些文件的拼接其实是相互独立的,可以充分利用cpu资源,进行并行处理,以大大加快处理的时间。GNU Parallel就是这样一个并行工具。通过下面的一行命令就解决了前面的问题

ls | parallel -m -j $f "cat {}>> ../transactions_cat/transactions.csv"


其中-j参数是并行数,默认情况下任务数是和cpu核数相同,设置为0时表示尽可能多的并行任务。

下图为执行时间和任务数的关系。



不难看出,执行速度和并行任务数之间并不成线性关系,当任务数到了一定数量的时候,增加任务数并不能明显提高执行效率。

这样,大量的文件被整合到了一起,再用hadoop处理起来就相当高效了。除此之外GNU Parallel还有很多丰富的功能,感兴趣的朋友可以了解一下。

附录:

GNU Parallel的安装:

1.Ubuntu:

下载安装包:GNU Parallel安装包下载

解压:tar xjvf parallel_20120422-1.debian.tar.gz

配置环境:./configure

安装:make install

2.Fedora:

直接命令安装:yum install parallel

3.Mac OSX:

直接命令安装:brew install parallel

参考:

http://www.gnu.org/software/parallel/parallel_tutorial.html#GNU-Parallel-Tutorial
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: