使用 Python 处理大文件有什么推荐的方式么?

2017-09-23 02:14:15 +08:00
 linuxchild

大概五六个 G 的文件,目前分割成了数个小文件,使用 multiprocessing 这种处理了一下,但是效率还是太低了

请问哪位有什么推荐的方法?

另外,我在尝试使用 pp 这个库,不过总是提示变量未定义,实际上已经定义了,使用 multiprocessing 这种都不会提示这个错误,使用的代码如下:

cpu_num = 8
job_server = pp.Server(cpu_num)
a =  []
for f in xxxxx:
    a.append(job_server.submit(func_name, (f, )))
for x in a:
    tmp = x()

有这方面经验的朋友帮一下忙,感谢

8124 次点击
所在节点    Python
46 条回复
sunchen
2017-09-23 11:35:22 +08:00
@linuxchild multiprocessing 啊
Wicked
2017-09-23 11:39:34 +08:00
Linux 应该也有类似的机制,可以查下文档。还是建议 profile 先,先从算法本身优化,热点再用 C++写一下。如果你要干的事情确实就有这么多,那你唯一可以干的就是把 CPU 吃满,换 SSD,加机器
laqow
2017-09-23 11:49:07 +08:00
感觉 python 原生解析文本的几个函数效率很低,没压缩只有几个 G 的文件问题可能在这里,应该和多进程无关
FindHao
2017-09-23 11:50:00 +08:00
@cdwyd 很可能,哈哈。
gamexg
2017-09-23 11:58:04 +08:00
>>现在的速度是 1h 处理 5-6w
6w/60/60 = 16.66666666666667

1 秒不到 17 条?
不知道读出来做的什么处理,所以不确定是不是出问题的地方。
你先试试只读取+处理不写看看性能,怀疑每次写都强制 sync 了。
billion
2017-09-23 11:59:55 +08:00
我有处理 40G 文本文件的经验。

我的文本文件每一行都是一个 JSON,用 Python 读取出来,再把每一行的 JSON 转成字典并插入到 MongoDB 中。使用 Python 的 readline()一行一行读,凑够了 10000 个字典以后一次性插入 MongoDB,亲测单线程单进程 4 个小时不到就跑完了。
aru
2017-09-23 12:31:40 +08:00
@linuxchild
单线程处理一下,看一下读取 /处理 /写入分别的耗时是多少
找到瓶颈才好优化
scys
2017-09-23 12:31:44 +08:00
建议你重点在优化算法逻辑处理部分,py 读 /写文件不是关键点。
尝试下 pypy 看能不能改善。
linuxchild
2017-09-23 12:32:05 +08:00
@gamexg 经你这么一说,仿佛明白了一些,做的解密处理…应该是这个原因

去掉解密,只读写没什么问题,很快…


@laqow 解析倒是没啥问题,只是 split 一下;问题应该在处理对过程,我做的解密处理…


@sunchen 现在用了这个,效果不太好。 试了一下 pp 想并行一下,结果出现了题目里对错误


@billion 这么一说更觉得是我处理过程导致的速度慢了,我做的解密处理……
linuxchild
2017-09-23 13:00:43 +08:00
@scys 嗯,主要是数据处理这里,我处理的是加解密,瓶颈应该是在这里… pypy 无力,在服务器上,装个软件都是运帷去搞

在想办法提高看看怎么并行处理一下


@aru 嗯,瓶颈应该是解密这里了…目前还没有找到好的办法

楼上说的 dask 还有我尝试的 pp 居然都碰到了错误…… pyspark 环境也有问题,想死
laxenade
2017-09-23 13:25:06 +08:00
假设一小时单线程能处理 6w 行,那四核(超线程在这里的用途应该不大)的服务器一天也只能跑 576w 行呢。所以你有可能需要换一个更快的库或者换一个语言(
scys
2017-09-23 13:28:56 +08:00
加解密你找个有 C 的模块,快起码不是一个数量级。

或者你说说你现在有的啥模块?
est
2017-09-23 13:39:14 +08:00
dask

mmap
linuxchild
2017-09-23 14:36:57 +08:00
@laxenade 服务器上跑的话,如果这样算,也只能尝试多几用几个核了……


@scys 用的 pycrypto …有什么推荐的模块么


@est 刚刚试了一下 dask

```
from dask import delayed
#import dask.bag as db
L = []
for fn in en_files:
# b = db.read_text(fn)
a = delayed(fun_name)(fn) # Delay execution of function
L.append(a)
result = delayed(L)
result.compute()
```
使用这种方式处理,发现和下面这种方式处理效率相似,看了看 cpu 占用率也很相似,大概都是单核 100%左右

```
#pool = ThreadPool(20)
#pool.map(decrypt_file, encrypt_files)
#pool.close()
#pool.join()
```

话说这是我使用方式的问题,还是什么?
laxenade
2017-09-23 14:46:17 +08:00
@linuxchild #34 所以差不多要 8 核 16 线程才能满足呢
linuxchild
2017-09-23 14:55:03 +08:00
@laxenade #35

- -。要是可以的话也想试试,先跑一下看看
用 pp 试了一下总是提示变量未定义
scys
2017-09-23 15:59:38 +08:00
scys
2017-09-23 16:04:18 +08:00
laqow
2017-09-23 16:12:43 +08:00
可能还是在 io,for fn in en_files 这个依赖系统硬盘缓存的,如果行数多但每行字少的时候很慢,主进程一次一行的分配任务会把主进程的 cpu 耗尽,不如一次 readlines 几千行塞到各个进程里在内存里由各个进程逐行处理。而且不知道为什么 python 解析 utf8 奇慢,全英文的转成其他编码的再处理。我以前遇到是这种问题。
numoone
2017-09-23 17:09:50 +08:00
难道都没看到楼主要处理的主要是加解密吗?瓶颈绝对值这啊!加解密模块用 C 来写吧!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/392983

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX