当前位置: 首页 > 面试题库 >

处理大文件的最快方法?

端木元青
2023-03-14
问题内容

我有多个3 GB的制表符分隔文件。每个文件中有2000万行。所有行都必须独立处理,任何两行之间都没有关系。我的问题是,什么会更快A.使用以下命令逐行阅读:

with open() as infile:
    for line in infile:

还是B.将文件分块读取到内存中并进行处理,例如一次250 MB?

处理不是很复杂,我只是在column1到List1column2的值中抓取值,List2等等。可能需要将一些列值加在一起。

我在具有30GB内存的Linux机器上使用python 2.7。ASCII文本。

有什么办法可以并行加速吗?现在,我正在使用前一种方法,该过程非常缓慢。使用任何CSVReader模块都会有所帮助吗?我不必用python来做,欢迎任何其他语言或数据库使用的想法。


问题答案:

听起来您的代码受I / O约束。这意味着多处理将无济于事-如果您花费90%的时间从磁盘读取数据,那么等待下一次读取的额外7个进程将无济于事。

而且,尽管使用CSV读取模块(无论是stdlibcsv还是NumPy或Pandas之类的东西)可能都是一个简单的好主意,但不太可能在性能上产生很大差异。

尽管如此,还是值得检查一下您是否确实 I /
O约束,而不仅仅是猜测。运行程序,查看您的CPU使用率是接近0%还是接近100%还是一个核心。执行Amadan在注释中建议的操作,然后仅pass出于处理目的运行您的程序,看看这是减少5%的时间还是减少70%的时间。你甚至可以尝试用遍历比较os.openos.read(1024*1024)什么的,看看这是任何更快。

由于您使用的是Python 2.x,因此Python依靠C
stdio库来一次猜测要缓冲多少,因此可能值得强迫它缓冲更多。最简单的方法是使用readlines(bufsize)一些大型的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)

Pythonmmap有点像一个怪异的对象,它的作用类似于strfile,因此,例如,您可以手动迭代扫描换行符,也可以readline像对待文件一样对其进行调用。与将文件作为行或批处理进行迭代相比,这两种方法都将需要更多的Python处理readlines(因为C语言中的循环现在在纯Python中……尽管也许可以使用re或使用简单的Cython扩展来解决该问题?)
…但是,操作系统知道您正在使用映射进行操作的I / O优势可能会淹没CPU的劣势。

不幸的是,Python并未公开madvise您用于调整事物以优化C语言的调用(例如,显式设置MADV_SEQUENTIAL而不是让内核猜测或强制透明大页面),但实际上您可以使用ctypes该函数出libc



 类似资料:
  • 问题内容: 我正在使用Spring批处理下载一个大文件来处理它。场景很简单: 无需保存输入文件数据。 我们可能同时运行多个(相同场景的)作业实例 我正在寻找最佳实践来处理这种情况。 我是否应该创建Tasklet以便在本地下载文件,而不是通过常规步骤开始处理它? 在这种情况下,我需要考虑一些临时文件问题(确保删除了该文件,确保不覆盖其他临时文件,等等。) 另一方面,我可以下载它并将其保留在内存中,但

  • 问题内容: 当给定一个MAX_BUFFER_SIZE的缓冲区以及一个远远超过该缓冲区的文件时,怎么办: 以MAX_BUFFER_SIZE的块读取文件? 尽快完成 我尝试使用NIO 和常规IO 事实证明, 常规IO在执行与NIO相同的操作时快约100倍 。我想念什么吗?这是预期的吗?有没有更快的方法来读取缓冲区块中的文件? 最终,我正在处理一个大文件,但我没有足够的内存来一次读取所有文件。相反,我想

  • 本文向大家介绍Python文本处理之按行处理大文件的方法,包括了Python文本处理之按行处理大文件的方法的使用技巧和注意事项,需要的朋友参考一下 以行的形式读出一个文件最简单的方式是使用文件对象的readline()、readlines()和xreadlines()方法。 Python2.2+为这种频繁的操作提供了一个简化的语法——让文件对象自身在行上高效迭代(这种迭代是严格的向前的)。 为了读

  • 上周,我决定尝试Perl6,并开始重新实现我的一个程序。我不得不说,Perl6对于对象编程来说非常容易,这对我来说是Perl5非常痛苦的一个方面。 我的程序必须读取和存储大文件,如整个基因组(高达3 Gb或更多,见下面的例子1)或制表数据。 代码的第一个版本是通过逐行迭代以Perl5的方式制作的(“基因组.fa”。对于正确的执行时间,它非常慢且不可行。 所以经过一点RTFM之后,我改变了文件上的s

  • 问题内容: 我正在Linux系统上使用非常大的文本文件(〜11GB)。我正在通过正在检查文件错误的程序来运行它。一旦发现错误,我需要修复该行或完全删除该行。然后重复… 最终,一旦我对流程感到满意,我便将其完全自动化。但是,现在让我们假设我正在手动运行它。 从此大文件中删除特定行最快(就执行时间而言)是什么?我想到了用Python进行此操作…但是可以接受其他示例。该行可能在文件中的 任何位置 。 如

  • 我正在导入大小为24MB的csv文件,但每次它都被截断为0KB,并显示以下错误。 导入Csv:无法处理参数,因为参数“name”的值无效。更改“name”参数的值,然后再次运行该操作。 $data=导入Csv 在此对象上找不到属性“Column4”;确保它存在且可设置。 CategoryInfo:InvalidOperation:(Column4:String)[],RuntimeExceptio