【问题标题】:Is python automagically parallelizing IO- and CPU- or memory-bound sections?python 是否自动并行化 IO 和 CPU 或内存绑定部分?
【发布时间】:2009-05-13 23:21:09
【问题描述】:

这是previous one 的后续问题。

考虑一下这段代码,它比previous question 中的代码少玩具(但仍然比我的真实代码简单得多)

import sys
data=[]

for line in open(sys.argv[1]):
    data.append(line[-1])

print data[-1]

现在,我期待更长的运行时间(我的基准文件有 65150224 行长),可能更长。事实并非如此,它在大约 2 分钟内运行在与以前相同的硬件上!

data.append() 是不是很轻量级?我不相信,所以我写了这个假代码来测试它:

data=[]
counter=0
string="a\n"

for counter in xrange(65150224):
    data.append(string[-1])

print data[-1]

这在 1.5 到 3 分钟内运行(运行之间存在很大差异)

为什么我在前一个程序中没有得到 3.5 到 5 分钟的时间?显然 data.append() 与 IO 并行发生。

这是个好消息!

但是它是如何工作的呢?它是记录在案的功能吗?对我的代码是否有任何要求以使其尽可能地工作(除了负载平衡 IO 和内存/CPU 活动)?还是只是简单的缓冲/缓存在起作用?

再次,我将这个问题标记为“linux”,因为我只对特定于 linux 的答案感兴趣。如果您认为值得这样做,请随意给出与操作系统无关的甚至是其他操作系统的答案。

【问题讨论】:

标签: python linux performance text-files


【解决方案1】:

显然 data.append() 与 IO 并行发生。

恐怕不会。 可以在 Python 中并行化 IO 和计算,但它不会神奇地发生。

您可以做的一件事是使用 posix_fadvise(2) 向操作系统提示您计划按顺序读取文件 (POSIX_FADV_SEQUENTIAL)。

在对 600 meg 文件(ISO)执行“wc -l”的一些粗略测试中,性能提高了大约 20%。每个测试都是在清除磁盘缓存后立即完成的。

有关流行的 Python 接口,请参阅python-fadvise

【讨论】:

    【解决方案2】:

    文件中的行有多大?如果它们不是很长(大约 1K 以下的任何东西都可能符合条件),那么您可能会因为输入缓冲而看到性能提升。

    【讨论】:

      【解决方案3】:

      为什么你认为 list.append() 会是一个较慢的操作?它非常快,考虑到列表用于保存对其中对象的引用的内部指针数组被分配在越来越大的块中,因此每个追加实际上都不会重新分配数组,并且大多数可以简单地增加长度计数器和设置一个指针和增量。

      【讨论】:

      • 嗯,它正在分配内存,这通常不是一个轻量级的过程。我不知道 python VM 的详细信息,但它要么分配 65150224 个小对象(可能很快,但重复太多次),或者更有可能在整个程序期间将分配大小增加一倍〜 26 次(2^26 ~ 64M)在越来越大的内存块中,可能由于内存碎片(或碎片整理?)而更难找到
      【解决方案4】:

      我没有看到任何证据表明“data.append() 与 IO 并行发生”。像 Benji 一样,我不认为这会像你想的那样是自动的。您展示了执行 data.append(line[-1]) 所需的时间与 lc = lc + 1 大致相同(与 IO 和行拆分相比,基本上没有时间)。 data.append(line[-1]) 非常快并不奇怪。人们会期望整行都在一个快速缓存中,并且如前所述,append 会提前准备缓冲区,并且很少需要重新分配。此外, line[-1] 将始终为 '\n',除了文件的最后一行(不知道 Python 是否对此进行了优化)。

      唯一让我有点惊讶的是 xrange 的变化如此之大。我希望它总是更快,因为没有 IO,而且您实际上并没有使用计数器。

      【讨论】:

        【解决方案5】:

        如果您的运行时间在第二个示例中的变化量如此之大,我怀疑您的计时方法或外部影响(其他进程/系统负载)会将时间扭曲到没有给出任何结果的地步可靠的信息。

        【讨论】:

        • 当然你可能是对的。但这也可能是内存碎片,不是吗?
        • 我不愿将内存碎片归咎于如此巨大的差异。我不能肯定地说,但我倾向于相信 Python 中的许多数据结构由于语言的性质而受到碎片化的影响。对于这种特定情况,我可能认为交换比碎片更可能是罪魁祸首。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-31
        • 1970-01-01
        • 2012-06-02
        • 2020-11-15
        • 2019-09-05
        • 2011-04-12
        相关资源
        最近更新 更多