Numpy with Combinatoric generator:如何加速组合?

时间:2013-01-23 04:16:03

标签: python performance numpy itertools

我的理解是itertools functions are written in C。如果我想加快这个示例代码:

import numpy as np
from itertools import combinations_with_replacement

def combinatorics(LargeArray):
     newArray = np.empty((LargeArray.shape[0],LargeArray.shape[0]))
     for x, y in combinations_with_replacement(xrange(LargeArray.shape[0]), r=2):
         z = LargeArray[x] + LargeArray[y]
         newArray[x, y] = z
     return newArray

由于combinations_with_replacement是用C语言编写的,这是否意味着它无法加速?请指教。

提前致谢。

1 个答案:

答案 0 :(得分:4)

combinations_with_replacement确实是用C语言编写的,这意味着您不太可能加快代码部分的实现速度。但是大部分代码都没有用于查找组合:它位于for循环中,用于添加。你真的,真的,真的想要避免这种循环,如果你在使用numpy时尽可能的话。这个版本通过the magic of broadcasting

几乎完成同样的事情
def sums(large_array):
    return large_array.reshape((-1, 1)) + large_array.reshape((1, -1))

例如:

>>> ary = np.arange(5).astype(float)
>>> np.triu(combinatorics(ary))
array([[ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  2.,  3.,  4.,  5.],
       [ 0.,  0.,  4.,  5.,  6.],
       [ 0.,  0.,  0.,  6.,  7.],
       [ 0.,  0.,  0.,  0.,  8.]])
>>> np.triu(sums(ary))
array([[ 0.,  1.,  2.,  3.,  4.],
       [ 0.,  2.,  3.,  4.,  5.],
       [ 0.,  0.,  4.,  5.,  6.],
       [ 0.,  0.,  0.,  6.,  7.],
       [ 0.,  0.,  0.,  0.,  8.]])

不同之处在于combinatorics将下三角形作为随机乱码,其中sums使矩阵对称。如果你真的想避免两次添加,你可能会,但我想不出如何做到这一点。

哦,另一个区别是:

>>> big_ary = np.random.random(1000)
>>> %timeit combinatorics(big_ary)
1 loops, best of 3: 482 ms per loop
>>> %timeit sums(big_ary)
1000 loops, best of 3: 1.7 ms per loop