【问题标题】:Why have I different results beween profiling List and Generator?为什么我在分析列表和生成器之间有不同的结果?
【发布时间】:2020-08-10 04:38:41
【问题描述】:

我正在研究图形上的 python 函数,它是递归和 NP 复杂的。但是,我在很长一段时间内得到了结果,所以我使用了 kernprof 来查看哪些行花费的时间更多。

我看到这条线比我想象的要花更多时间:

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
...
    53    120244     740797.0      6.2     17.0             if any( [m[passed].get(i, False) for passed in isom] ): # si ce noeud est lié à un noeud passé, le tester

所以我选择使用生成器,因为我似乎不应该生成所有列表,因为我只是感兴趣,如果有的话。

但是有了生成器,我得到了这个结果:

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
...
    53     35283     509901.0     14.5     12.8             if any( (m[passed].get(i, False) for passed in isom) ): # si ce noeud est lié à un noeud passé, le tester

所以它似乎比使用列表理解更快,但我不明白为什么每次点击的时间更大,为什么我的点击次数少得多?

【问题讨论】:

    标签: python performance generator


    【解决方案1】:

    rkern (https://github.com/rkern/line_profiler) 的常见问题解答:

    当我使用 LineProfiler 时,为什么我的列表推导有这么多命中?

    LineProfiler 为列表推导的每次迭代记录一次具有列表推导的行。

    这解释了为什么使用生成器每次点击的时间更高,就像在列表中一样,很多点击只是返回 false 的迭代,但使用生成器时,很多点击用于生成生成器,生成器速度较慢。

    【讨论】:

      【解决方案2】:

      看来你不是在比较橘子和橘子。

      列表理解上的命中似乎计算了列表中的项目。因为您实际上是在生成一个列表并且只将 any() 应用于结果对象,所以您将系统地遍历 isom 的所有元素(因此命中率很高)。

      迭代器不会遍历isom的所有元素。因此,命中的数量会根据图形的密度而有所不同,但通常会远低于列表理解(这总是会产生最坏的情况)

      至于每次点击的时间,您的总时间只小了一小部分(因为其他开销),但您的点击次数减少了一个数量级,因此每次点击的时间比率自然会更高。该比率实际上并没有衡量迭代器和列表理解之间的差异,因为点击不是在相同的基础上计算的。为了进行有意义的比较,您必须使用一个公约数(理想情况下是该行的实际执行次数)。如果您根据原始点击计数(即相同工作量 509901.0/120244 的总时间)比较每次点击的时间,那么迭代器的“每次点击”将为 4.2

      【讨论】:

        猜你喜欢
        • 2016-02-08
        • 2017-08-15
        • 2017-10-01
        • 1970-01-01
        • 2021-02-18
        • 1970-01-01
        • 2021-03-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多