我有多个 3 GB 制表符分隔文件。每个文件中有 2000 万行。所有行都必须独立处理,任何两行之间没有关系。我的问题是,什么会更快?
逐行阅读?
with open() as infile: for line in infile:
将文件分 block 读入内存并进行处理,比如一次 250 MB?
处理不是很复杂,我只是将column1中的值抓取到List1
,column2到List2
等。可能需要将一些列值添加在一起。
我在具有 30GB 内存的 linux 机器上使用 python 2.7。 ASCII 文本。
有什么方法可以并行加速?现在我使用的是前一种方法,过程很慢。使用任何 CSVReader
模块会有帮助吗?
我不必在 python 中做,欢迎任何其他语言或数据库使用想法。
最佳答案
听起来您的代码受 I/O 限制。这意味着多处理无济于事——如果您花费 90% 的时间从磁盘读取数据,那么在下一次读取时等待额外的 7 个进程也无济于事。
而且,虽然使用 CSV 读取模块(无论是 stdlib 的 csv
还是 NumPy 或 Pandas 之类的东西)可能是一个简单的好主意,但它不太可能对性能产生太大影响。
不过,值得检查一下您是否真的受 I/O 限制,而不仅仅是猜测。运行您的程序并查看您的 CPU 使用率是接近 0% 还是接近 100% 或核心。执行 Amadan 在评论中建议的操作,只使用 pass
运行您的程序进行处理,看看是否会减少 5% 或 70% 的时间。您甚至可能想尝试与 os.open
和 os.read(1024*1024)
上的循环进行比较,看看是否更快。
自从您使用 Python 2.x 以来,Python 依靠 C stdio 库来猜测一次要缓冲多少,因此可能值得强制它缓冲更多。最简单的方法是对一些较大的 bufsize
使用 readlines(bufsize)
。 (您可以尝试不同的数字并测量它们以查看峰值在哪里。根据我的经验,通常 64K-8MB 的任何东西都差不多,但取决于您的系统,可能会有所不同——尤其是如果您正在阅读关闭具有高吞吐量但可怕的延迟的网络文件系统,淹没了实际物理驱动器的吞吐量与延迟以及操作系统所做的缓存。)
所以,例如:
bufsize = 65536
with open(path) as infile:
while True:
lines = infile.readlines(bufsize)
if not lines:
break
for line in lines:
process(line)
同时,假设您使用的是 64 位系统,您可能想尝试使用 mmap
而不是首先读取文件。这当然不是保证会更好,但它可能会更好,具体取决于您的系统。例如:
with open(path) as infile:
m = mmap.mmap(infile, 0, access=mmap.ACCESS_READ)
Python mmap
是一种奇怪的对象——它既像 str
又像 file
,所以你例如,可以手动迭代扫描换行符,或者您可以在其上调用 readline
,就好像它是一个文件一样。与将文件作为行迭代或执行批处理 readlines
相比,这两者都需要从 Python 进行更多的处理(因为在 C 中的循环现在在纯 Python 中......尽管也许你可以用 re
,还是使用简单的 Cython 扩展?)...但是操作系统知道您正在使用映射做什么的 I/O 优势可能会淹没 CPU 的劣势。
不幸的是,Python 没有公开 madvise
调用你用来调整的东西,试图在 C 中优化它(例如,显式设置 MADV_SEQUENTIAL
而不是让内核猜测,或强制透明大页面) - 但你实际上可以 ctypes
libc
中的函数。
关于python - 处理大文件的最快方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30294146/