2010-01-01 48 views
4

我一直在做一些性能测试,以提高我写的宠物项目的性能。这是一个非常紧凑的应用程序,所以我一直在玩Numpy作为提高计算性能的一种方式。差numpy.cross()性能

然而,从下面的性能测试结果相当令人吃惊....

测试源代码(更新测试用例吊装和批量提交)

import timeit 

numpySetup = """ 
import numpy 
left = numpy.array([1.0,0.0,0.0]) 
right = numpy.array([0.0,1.0,0.0]) 
""" 

hoistSetup = numpySetup +'hoist = numpy.cross\n' 

pythonSetup = """ 
left = [1.0,0.0,0.0] 
right = [0.0,1.0,0.0] 
""" 

numpyBatchSetup = """ 
import numpy 

l = numpy.array([1.0,0.0,0.0]) 
left = numpy.array([l]*10000) 

r = numpy.array([0.0,1.0,0.0]) 
right = numpy.array([r]*10000) 
""" 

pythonCrossCode = """ 
x = ((left[1] * right[2]) - (left[2] * right[1])) 
y = ((left[2] * right[0]) - (left[0] * right[2])) 
z = ((left[0] * right[1]) - (left[1] * right[0])) 
""" 

pythonCross = timeit.Timer(pythonCrossCode, pythonSetup) 
numpyCross = timeit.Timer ('numpy.cross(left, right)' , numpySetup) 
hybridCross = timeit.Timer(pythonCrossCode, numpySetup) 
hoistCross = timeit.Timer('hoist(left, right)', hoistSetup) 
batchCross = timeit.Timer('numpy.cross(left, right)', numpyBatchSetup) 

print 'Python Cross Product : %4.6f ' % pythonCross.timeit(1000000) 
print 'Numpy Cross Product : %4.6f ' % numpyCross.timeit(1000000) 
print 'Hybrid Cross Product : %4.6f ' % hybridCross.timeit(1000000) 
print 'Hoist Cross Product : %4.6f ' % hoistCross.timeit(1000000) 
# 100 batches of 10000 each is equivalent to 1000000 
print 'Batch Cross Product : %4.6f ' % batchCross.timeit(100) 

原始结果

Python Cross Product : 0.754945 
Numpy Cross Product : 20.752983 
Hybrid Cross Product : 4.467417 

最终结果

Python Cross Product : 0.894334 
Numpy Cross Product : 21.099040 
Hybrid Cross Product : 4.467194 
Hoist Cross Product : 20.896225 
Batch Cross Product : 0.262964 

不用说,这不是结果我的预期。纯Python版本比Numpy执行速度快了近30倍。其他测试中的Numpy性能比Python相当好(这是预期的结果)。为什么NumPy的是在这种情况下进行如此糟糕

  • 谁能解释:

    所以,我有两个相关的问题?

  • 有什么我可以做的,以解决它?

回答

6

用更大的阵列试试这个。我认为这里调用numpy方法的代价超过了Python版本所需的简单的几个列表访问。如果你处理更大的阵列,我想你会看到numpy的大胜。

+0

在这种特殊情况下,3个分量数组(x,y,z坐标)是最常见的情况。也有点奇怪的是,即使从numpy数组中读取,Python代码仍然更快。如果是通话开销,我预计它会比纯粹的NumPy解决方案慢得多。 – 2010-01-01 08:39:01

+0

@Adam:但是通过从numpy的数组中读取数据,可以节省调用'cross'函数本身的开销,这是一个动态加载的扩展,所以它至少经历了几次指针。对于这样短的阵列,它确实很有意义,因为它是一个微调优化,可以将调用展开为'cross' – 2010-01-01 08:42:23

+0

我刚刚添加了一个测试用例,我将这些阵列分配在一起,并且看到了相当大的性能提升。所以我会说头顶理论是正确的。看起来如果我想用Numpy来提升性能,我需要找到一种将这些操作组合在一起的方法。 – 2010-01-02 02:57:07

0

优秀的文章!我认为比较并不公平。批交叉产品给出一个包含所有向量的交叉产品的数组,而Python交叉产品每次只给出一个向量。如果您需要一次计算所有交叉产品,当然Batch更好,但是如果您需要分别计算每个交叉产品,则应包括访问该阵列的开销。另外,如果交叉产品,如果以前的交叉产品的功能批处理实施应该被修改。