Why list comprehension is much faster than numpy for multiplying arrays?

后端 未结 1 985
南方客
南方客 2020-11-29 09:46

Recently I answered to THIS question which wanted the multiplication of 2 lists,some user suggested the following way using numpy, alongside mine which I think is the proper

相关标签:
1条回答
  • 2020-11-29 10:09

    Creation of numpy arrays is much slower than creation of lists:

    In [153]: %timeit a = [[2,3,5],[3,6,2],[1,3,2]]
    1000000 loops, best of 3: 308 ns per loop
    
    In [154]: %timeit a = np.array([[2,3,5],[3,6,2],[1,3,2]])
    100000 loops, best of 3: 2.27 µs per loop
    

    There can also fixed costs incurred by NumPy function calls before the meat of the calculation can be performed by a fast underlying C/Fortran function. This can include ensuring the inputs are NumPy arrays,

    These setup/fixed costs are something to keep in mind before assuming NumPy solutions are inherently faster than pure-Python solutions. NumPy shines when you set up large arrays once and then perform many fast NumPy operations on the arrays. It may fail to outperform pure Python if the arrays are small because the setup cost can outweigh the benefit of offloading the calculations to compiled C/Fortran functions. For small arrays there simply may not be enough calculations to make it worth it.


    If you increase the size of the arrays a bit, and move creation of the arrays into the setup, then NumPy can be much faster than pure Python:

    import numpy as np
    from timeit import timeit
    
    N, M = 300, 300
    
    a = np.random.randint(100, size=(N,M))
    b = np.random.randint(100, size=(N,))
    
    a2 = a.tolist()
    b2 = b.tolist()
    
    s1="""
    [[m*n for n in second] for m, second in zip(b2,a2)]
    """
    
    s2 = """
    (a.T*b).T
    """
    
    s3 = """
    a*b[:,None]
    """
    
    assert np.allclose([[m*n for n in second] for m, second in zip(b2,a2)], (a.T*b).T)
    assert np.allclose([[m*n for n in second] for m, second in zip(b2,a2)], a*b[:,None])
    
    print 's1: {:.4f}'.format(
        timeit(stmt=s1, number=10**3, setup='from __main__ import a2,b2'))
    print 's2: {:.4f}'.format(
        timeit(stmt=s2, number=10**3, setup='from __main__ import a,b'))
    print 's3: {:.4f}'.format(
        timeit(stmt=s3, number=10**3, setup='from __main__ import a,b'))
    

    yields

    s1: 4.6990
    s2: 0.1224
    s3: 0.1234
    
    0 讨论(0)
提交回复
热议问题