测量代码的执行时间,这取决于“设置顺序”

时间:2016-04-12 17:44:23

标签: python-2.7 optimization set timeit

问题描述:

我正在优化相当复杂的算法,遗憾的是,它非常依赖于使用setfrozenset数据类型(因为in运算符更快)。这意味着每次运行测试时都会得到不同的执行时间,即使对于完全相同的输入数据也是如此。由于我需要(非常)优化算法,我希望每次都有一个常量(尽可能)执行时间。

示范

我做了一个简化的例子,希望能够证明这个问题:

import timeit

class A(object):
    def __init__(self, val):
        self.val = val

def run_test():
    result = []
    for i in xrange(100):
        a = {A(j) for j in xrange(100)}
        result.append(sorted(v.val for v in a))
    return result

N = 10
times = timeit.Timer(run_test).repeat(repeat=3, number=N)
print '%.6f s' % (min(times) / N,)

问题的核心是sets中对象的排序 - 它取决于(我认为)他们在记忆中的位置,这当然每次都不同。然后,在对值进行排序时,每次sorted执行速度都会不同。在我的机器上,它的执行时间约为10%。 这不是最好的演示,因为我的真实代码更多地依赖于集合排序,时间差异要高得多,但我希望你能得到它。

我尝试了什么:

  • 对算法中的集合进行排序 - 它给出了恒定的执行时间,但也使整个算法慢了十倍
  • 使用非常大的numberrepeat参数 - 除非我想在每次更改后等待一个小时,否则我无法帮助

我想尝试一下:

我认为如果我能以某种方式“重置”python解释器以获得“干净的记忆”,它将导致对象的可预测的记忆位置,并且时间测量将是恒定的。但我不知道如何做这样的事情,除了创建一个虚拟机并在每次我想进行测试时重新启动它。 我想

不是问题:

  • 我描述了很多,而且我知道哪些功能现在最慢 - 我只需要让它们更快 - 这些是我试图测量的功能。
  • 我不能使用除setfrozenset之外的任何其他内容进行测试(就像某些有序集合一样),因为它会慢很多,并且测得的速度与生产无关代码
  • setfrozenset表现并不重要

摘要/问题:

  • 我的算法在内部使用sets
  • 我想测量执行速度
  • 执行速度取决于检索内部set中包含的元素的顺序
  • 我正在使用的测试具有固定的输入值
  • 根据timeit衡量标准,我无法衡量我所做的任何变更的影响
  • 在上面的测试中,run_test函数是我真正问题的一个很好的例子

所以我需要一些方法来临时确保所有set元素都将在相同的内存位置创建,这将使测试执行速度和函数调用数(分析)具有确定性。

附加示例

这个例子可能更好地证明了我的问题:

import timeit
import time

class A(object):
    def __init__(self, val):
        self.val = val

    def get_value_from_very_long_computation(self):
        time.sleep(0.1)
        return self.val

def run_test():
    input_data = {A(j) for j in xrange(20)}

    for i, x in enumerate(input_data):
        value = x.get_value_from_very_long_computation()
        if value > 16:
            break
    print '%d iterations' % (i + 1,)

times = timeit.Timer(run_test).repeat(repeat=1, number=1)
print '%.9f s' % (min(times) / N,)

返回,例如:

$ ./timing-example2.py 
4 iterations
0.400907993 s

$ ./timing-example2.py 
3 iterations
0.300778866 s

$ ./timing-example2.py 
8 iterations
0.801693201 s

(当然,每次运行时都会有所不同,在另一台机器上可能会有所不同或完全不同)

您可以看到每次输入数据保持完全相同时执行速度非常不同。这正是我在测量算法速度时看到的行为。

0 个答案:

没有答案