好吧,伙计们,我有个答案:纽比的vectorize。在
不过,请阅读编辑过的部分。您将发现python实际上为您优化了代码,这实际上违背了在本例中使用numpy数组的目的。(但使用numpy数组不会降低性能。)
最后一个测试真正表明python列表是尽可能有效的,因此这个向量化过程是不必要的。这就是为什么我没有把这个问题标为“最佳答案”。在
设置代码:def factory(i): return lambda num: num==i
array1 = list()
for i in range(10000): array1.append(factory(i))
array1 = np.array(array1)
array2 = np.array(xrange(10000))
“无部门”版本:
^{pr2}$
矢量化版本def evaluate2(func, b): return func(b)
vec_evaluate = np.vectorize(evaluate2)
vec_evaluate(array1, array2)
# 100 loops, best of 3: 2.65 ms per loop
编辑
好的,我只想粘贴更多的基准测试,我收到使用以上测试,除了不同的测试用例。在
我做了第三次编辑,展示了如果只使用python列表会发生什么。长话短说,你其实不会后悔太多。这个测试用例在最底层。在
只涉及整数的测试用例
总而言之,如果n很小,那么无扇区的版本更好。否则,矢量化是正确的选择。在
带n = 30%timeit evaluate(array1, array2)
# 10000 loops, best of 3: 35.7 µs per loop
%timeit vec_evaluate(array1, array2)
# 10000 loops, best of 3: 27.6 µs per loop
带n = 7%timeit evaluate(array1, array2)
100000 loops, best of 3: 9.93 µs per loop
%timeit vec_evaluate(array1, array2)
10000 loops, best of 3: 21.6 µs per loop
涉及字符串的测试用例
矢量化获胜。在
设置代码:def factory(i): return lambda num: str(num)==str(i)
array1 = list()
for i in range(7):
array1.append(factory(i))
array1 = np.array(array1)
array2 = np.array(xrange(7))
与n = 10000%timeit evaluate(array1, array2)
10 loops, best of 3: 36.7 ms per loop
%timeit vec_evaluate(array1, array2)
100 loops, best of 3: 6.57 ms per loop
带n = 7%timeit evaluate(array1, array2)
10000 loops, best of 3: 28.3 µs per loop
%timeit vec_evaluate(array1, array2)
10000 loops, best of 3: 27.5 µs per loop
随机测试
只是想看看分支预测是如何发挥作用的。据我所见,其实没什么变化。矢量化通常仍然是成功的。在
设置代码。在def factory(i):
if random() < 0.5:
return lambda num: str(num) == str(i)
return lambda num: num == i
当n = 10000%timeit evaluate(array1, array2)
10 loops, best of 3: 25.7 ms per loop
%timeit vec_evaluate(array1, array2)
100 loops, best of 3: 4.67 ms per loop
当n = 7%timeit evaluate(array1, array2)
10000 loops, best of 3: 23.1 µs per loop
%timeit vec_evaluate(array1, array2)
10000 loops, best of 3: 23.1 µs per loop
使用python列表而不是numpy数组
我运行这个测试来看看当我选择不使用“优化的”numpy数组时发生了什么,我得到了一些非常令人惊讶的结果。在
设置代码几乎相同,只是我选择不使用numpy数组。我也在做这个测试,只针对“随机”的情况。在def factory(i):
if random() < 0.5:
return lambda num: str(num) == str(i)
return lambda num: num == i
array1 = list()
for i in range(10000): array1.append(factory(i))
array2 = range(10000)
以及“无部门”的版本:%timeit evaluate(array1, array2)
100 loops, best of 3: 4.93 ms per loop
您可以看到这实际上是相当令人惊讶的,因为这几乎是我在随机测试用例中收到的关于向量化evaluate的基准测试。在%timeit vec_evaluate(array1, array2)
10 loops, best of 3: 19.8 ms per loop
同样,如果您在使用vec_evaluate之前将这些数组更改为numpy数组,您将获得相同的4.5ms基准测试。在