代码之家  ›  专栏  ›  技术社区  ›  Adam Luchjenbroers

numpy.cross()性能不佳

  •  5
  • Adam Luchjenbroers  · 技术社区  · 15 年前

    我一直在做一些性能测试,以提高我正在写的一个宠物项目的性能。这是一个非常复杂的应用程序,所以我一直在用numpy来提高计算性能。

    但是,下面的性能测试的结果非常令人惊讶….

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

    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在这种情况下表现如此糟糕吗?
    • 我能做些什么来修理它吗?
    4 回复  |  直到 10 年前
        1
  •  6
  •   Eli Bendersky    15 年前

    尝试使用较大的数组。我认为这只是调用 numpy 这里超越了Python版本所需的简单的几个列表访问。如果你处理更大的阵列,我想你会看到 麻木的 .

        2
  •  5
  •   dmazzoni    15 年前

    您可以在这里看到源代码: http://www.google.com/codesearch/p?hl=en#5mAq98l-MUw/trunk/dnumpy/numpy/core/numeric.py&q=cross%20package:numpy&sa=N&cd=1&ct=rc

    numpy.cross只处理大量的案例,并做一些额外的拷贝。

    一般来说,numpy的速度会很快,足以应付矩阵乘法或求逆之类的慢运算,但是像这样的小向量运算会有很多开销。

        3
  •  1
  •   Ryan Ginstrom    15 年前

    为了减少numpy调用开销,您可以尝试使用cython作为调用numpy函数的中介。

    Fast numerical computations with Cython (SciPy 2009) 详情。

        4
  •  0
  •   nodarkside    10 年前

    棒极了!我认为这种比较实际上不公平。批处理交叉积给出一个包含所有向量交叉积的数组,而python交叉积则一次给出一个向量。如果您需要一次计算所有的交叉产品,当然批处理更好,但是如果您需要单独计算每个交叉产品,您应该包括访问数组的开销。另外,如果是一个跨产品,如果是前一个跨产品的函数,则应该修改批处理实现。