2

最近我一直在对我的脚本进行一些时间分析。想知道元组理解我在 SO 上发现了几个线程,指出了两种方法:

  • 列表理解 + tuple()

    >>> tuple([i for i in xrange(1000000)])
    
  • 元组理解

    >>> tuple(i for i in xrange(1000000))
    

我对这样一个事实感到困惑,cProliletimeit告诉我第一种方法比第二种方法更快,而命令行timekernprof行分析器则相反。

这是我得到的:

>>> import cProfile
>>> cProfile.run('tuple([i for i in xrange(1000000)])')
1000003 function calls in 0.139 seconds
>>> cProfile.run('tuple(i for i in xrange(1000000))')
1000003 function calls in 0.478 seconds 

>>> import timeit
>>> timeit.timeit('tuple([i for i in xrange(1000000)])')
0.08100390434265137
>>> timeit.timeit('tuple(i for i in xrange(1000000))')
0.08400511741638184

使用 test_tuple_list.py:

tuple([i for i in xrange(1000000)])

和 test_tuple_generator.py:

tuple(i for i in xrange(1000000))

我得到:

$time python test_tuple_list.py
real 0m0.398s
user 0m0.171s
sys 0m0.202s

$time python test_tuple_generator.py
real 0m0.333s
user 0m0.109s
sys 0m0.234s

使用 test_tuple_list_kernprof.py

@profile
def test():
    tuple([i for i in xrange(1000000)])
test()

和 test_tuple_generator_kernprof.py:

@profile
def test():
   tuple(i for i in xrange(1000000))
test()

我得到:

$kernprof.py -lv test_tuple_list_kernprof.py
Total time: 0.861045 s

$kernprof.py -lv test_tuple_generator_kernprof.py
Total time: 0.444025 s

我假设我在这些分析器之间得到的差异来自于它们的分析方式,但是它们为什么会相互矛盾呢?

谢谢

4

1 回答 1

1

不要使用分析器来测量两个 Python 代码片段之间的总体时序差异。配置文件严重影响整个解释器的代码执行时间,因为不同的代码路径将在不同的时间触发sys.set_trace()跟踪函数,并且跟踪函数本身可能会为不同的事件引入细微的时序差异,从而完全扭曲结果,使您的数据无法用于绝对时序比较.

在进行分析时,您测量分析器对不同代码路径的反应与测量代码路径本身一样多。当您想查明所有执行时间在复杂代码中的位置时,这很好但是仅根据它们的执行速度比较两段不同的代码是很糟糕的。

剩下的只是你的timeit结果,这些结果太接近了。这两种方法的速度差不多。

于 2013-07-25T14:21:01.777 回答