【问题标题】:Generator speed in python 3python 3中的发电机速度
【发布时间】:2010-03-08 04:35:22
【问题描述】:

我正在查看某人发布的link about generators。一开始他比较了下面的两个函数。在他的设置中,他的发电机速度提高了 5%。

我正在运行 windows XP、python 3.1.1,并且似乎无法复制结果。当使用提供的日志和最多 1GB 的重复数据进行测试时,我一直显示“旧方式”(logs1)稍微快一些。

有人能帮我理解发生了什么不同吗?

谢谢!

def logs1():
    wwwlog = open("big-access-log")
    total = 0
    for line in wwwlog:
        bytestr = line.rsplit(None,1)[1]
        if bytestr != '-':
            total += int(bytestr)
    return total

def logs2():
    wwwlog = open("big-access-log")
    bytecolumn = (line.rsplit(None,1)[1] for line in wwwlog)
    getbytes      = (int(x) for x in bytecolumn if x != '-')
    return sum(getbytes)

*编辑,复制/粘贴中的间距搞砸了

【问题讨论】:

  • 在我看来这两个功能本质上是相同的。在这两种情况下,您都没有构建一个庞大的列表,而您本来可以使用生成器。所以我对它们的运行速度差不多并不感到惊讶。
  • 有道理,我只是好奇为什么他的速度提高了 5%,而我看到的速度一直在下降 1%。

标签: python python-3.x


【解决方案1】:

不管怎样,演示中速度比较的主要目的是指出使用生成器不会带来巨大的性能开销。许多程序员在第一次看到生成器时,可能会开始想知道隐藏的成本。例如,幕后是否有各种奇特的魔术?使用此功能会使我的程序运行速度变慢吗?

通常情况并非如此。该示例旨在表明生成器解决方案可以以基本相同的速度运行,即使在某些情况下速度不会稍微快一些(尽管这取决于情况、Python 版本等)。如果您发现两个版本之间的性能存在巨大差异,那么这将是值得研究的事情。

【讨论】:

    【解决方案2】:

    在您链接到的 David Beazley 的幻灯片中,他说所有测试都是使用“OS X 10.4.11 上的 Python 2.5.1”运行的,并且您说您正在 Windows XP 上使用 Python 3.1 运行测试。所以,意识到你正在做一些苹果和橘子的比较。我怀疑这两个变量,Python 版本更重要。

    Python 3 与 Python 2 是不同的野兽。许多事情在底层发生了变化(甚至在 Python 2 分支中)。这包括性能优化和性能回归(例如,参见Beazley's own recent blog post on I/O in Python 3)。出于这个原因,Python Performance Tips 页面明确声明,

    您应该始终使用 您的应用程序和版本 你打算使用的 Python 而不仅仅是 盲目地接受一种方法是 比另一个更快。

    我应该提到,您可以依靠生成器帮助的一个领域是减少 内存 消耗,而不是 CPU 消耗。如果您有大量数据可以从每个单独的部分中计算或提取某些内容,并且之后不需要这些数据,那么生成器就会大放异彩。详情请见generator comprehension

    【讨论】:

    • 明白,我很怀疑这就是为什么我发布我使用python3。同样,我很好奇发生了什么不同的事情。
    • 如果您真的很好奇,请尝试使用 Python 2.6 安装运行计时测试;如果这对您没有影响,请尝试安装 Python 2.5,看看您是否仍然无法复制 Beazley 的结果。或者你也可以像我一样偷懒,直接给 Python-dev 发邮件。
    【解决方案3】:

    差不多半小时后你没有答案。我发布了一些对我有意义的东西,不一定是正确的答案。我认为这在将近半小时后总比没有好:

    第一个算法使用生成器。生成器通过加载列表中的第一个结果page(到内存中)来运行,并不断加载后续页面(到内存中),直到没有任何内容可以从输入中读取。

    第二种算法使用两个生成器,每个生成器都有一个if 语句,每个循环总共进行两次比较,而不是第一种算法的一次比较。

    另外,第二个算法在最后调用sum 函数,而第一个算法只是在遇到相关整数时不断添加相关整数。

    因此,对于足够大的输入,第二种算法比第一种算法有更多的比较和额外的函数调用。这或许可以解释为什么它比第一个算法需要更长的时间。

    希望对你有帮助

    【讨论】:

    • “另外,第二种算法在最后调用 sum 函数,而不是第一种算法,它只是在遇到相关整数时不断添加相关整数。”我认为这没有什么区别,因为 sum() 可能不会将所有值都放入内存然后添加它们。它可能会在迭代时添加它们,就像其他代码一样。
    猜你喜欢
    • 2011-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-25
    • 2018-12-15
    • 1970-01-01
    • 1970-01-01
    • 2019-08-27
    相关资源
    最近更新 更多