Python整数比较(不等于0)基准测试

时间:2018-04-06 10:12:49

标签: python python-3.x optimization timing

我正在python中创建一个2D物理引擎以获得乐趣。我使用对象的速度来确定是否应该在其上运行碰撞检测。即如果它的速度会导致它在下一个循环中位于另一个对象内部,那么我就会对它进行碰撞检测。

注意:x和y速度总是整数

所以我意识到我必须检查对象的x或y速度是否小于或大于(不是)0。

有很多方法可以做到这一点。我提出了4种不同的方法:

def cmp1 (a,b):
    return a > 0 or a < 0 or b > 0 or b < 0

def cmp2 (a, b):
    return a != 0 or b != 0

def cmp3 (a, b):
    return abs(a | b) > 0

def cmp4 (a, b):
    return a | b != 0

我喜欢第四种方法,因为它的操作最少,并且英文读得很好 a or b does not equal 0

但是在我使用的4种方法和基准测试方法中,它具有第二慢的平均时间让我感到惊讶。事实上,第一种方法是最快的(再次,使用我使用的基准测试方法)。

以下是我用来计算时间的方法:

def randints(min, max, amount):
    return tuple([random.randint(min, max) for i in range(amount)])

times = []
for i in range(1000):
    n = randints(-9999, 9999, 2)
    t = time.time() * 1000
    cmp4(*n)
    t2 = time.time() * 1000
    times.append(t2-t)

print('Average Time: ', sum(times)/len(times))

如果我为每种方法多次运行,我会得到非常一致的结果:

cmp1 - 0.00027s

cmp2 - 0.00032s

cmp3 - 0.00037s

cmp4 - 0.00035s

所以我的问题是为什么第四种方法与第一种方法相比这么慢?肯定有2次操作(一次按位,一次比较)应该比4快。

而且,是的,我知道它只有几微秒的差异。

1 个答案:

答案 0 :(得分:2)

有更好的测试方法

y = [(random.randint(0,1), random.randint(0,1)) for _ in range(100_000)]

def test(cmp):
    [cmp(a, b) for a, b in y]

%timeit test(cmp1)
20.1 ms ± 315 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit test(cmp2)
17.3 ms ± 212 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit test(cmp3)
29.3 ms ± 588 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit test(cmp4)
21.9 ms ± 289 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

or的主要优点是它是短路的,实际上相当于:

def or(a, b):
    if a: return a
    return b

|需要执行实际(非常低级别)操作,然后创建一个新的python整数对象,然后执行另一个操作。

我的测试使用50%零的数组。如果零的百分比更大或更小,结果可能会大不相同。

无论如何,你忘记了最快的方法(因为所有非零数字都是True):

def cmp0(a, b):
    return a or b

bool(cmp0(0, 0)), bool(cmp0(-12, 0)), bool(cmp0(3.14, 0))
# --> (False, True, True)

%timeit test(cmp0)
12.8 ms ± 191 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

但是如果你想尽可能清楚(在python编程的核心),我会使用a != 0 or b != 0