【问题标题】:Why is numpy slower than python? How to make code perform better为什么numpy比python慢​​?如何让代码性能更好
【发布时间】:2013-05-16 20:40:31
【问题描述】:

我将我的神经网络从纯 python 改写为 numpy,但现在它的工作速度更慢。所以我尝试了这两个功能:

def d():
    a = [1,2,3,4,5]
    b = [10,20,30,40,50]
    c = [i*j for i,j in zip(a,b)]
    return c

def e():
    a = np.array([1,2,3,4,5])
    b = np.array([10,20,30,40,50])
    c = a*b
    return c

时间 d = 1.77135205057

timeit e = 17.2464673758

Numpy 慢了 10 倍。为什么会这样以及如何正确使用numpy?

【问题讨论】:

标签: python performance numpy


【解决方案1】:

我认为差异是因为您在e 中构造列表和数组,而您只是在d 中构造列表。考虑:

import numpy as np

def d():
    a = [1,2,3,4,5]
    b = [10,20,30,40,50]
    c = [i*j for i,j in zip(a,b)]
    return c

def e():
    a = np.array([1,2,3,4,5])
    b = np.array([10,20,30,40,50])
    c = a*b
    return c

#Warning:  Functions with mutable default arguments are below.
# This code is only for testing and would be bad practice in production!
def f(a=[1,2,3,4,5],b=[10,20,30,40,50]):
    c = [i*j for i,j in zip(a,b)]
    return c

def g(a=np.array([1,2,3,4,5]),b=np.array([10,20,30,40,50])):
    c = a*b
    return c


import timeit
print timeit.timeit('d()','from __main__ import d')
print timeit.timeit('e()','from __main__ import e')
print timeit.timeit('f()','from __main__ import f')
print timeit.timeit('g()','from __main__ import g')

这里的函数fg 避免了每次都重新创建列表/数组,我们得到了非常相似的性能:

1.53083586693
15.8963699341
1.33564996719
1.69556999207

请注意 list-comp + zip 仍然获胜。但是,如果我们使数组足够大,numpy 会胜出:

t1 = [1,2,3,4,5] * 100
t2 = [10,20,30,40,50] * 100
t3 = np.array(t1)
t4 = np.array(t2)
print timeit.timeit('f(t1,t2)','from __main__ import f,t1,t2',number=10000)
print timeit.timeit('g(t3,t4)','from __main__ import g,t3,t4',number=10000)

我的结果是:

0.602419137955
0.0263929367065

【讨论】:

    【解决方案2】:
    import time , numpy
    def d():
        a = range(100000)
        b =range(0,1000000,10)
        c = [i*j for i,j in zip(a,b)]
        return c
    
    def e():
        a = numpy.array(range(100000))
        b =numpy.array(range(0,1000000,10))
        c = a*b
        return c
    
    
    
    #python ['0.04s', '0.04s', '0.04s']
    #numpy ['0.02s', '0.02s', '0.02s']
    

    尝试使用更大的数组...即使创建数组的开销 numpy 更快

    【讨论】:

    • 与小数据的 10 倍损失相比,2 倍微不足道。成为间接成本的牺牲品要容易得多。
    • 非常有效的观点。
    【解决方案3】:

    Numpy 数据结构的添加/构造速度较慢

    这里有一些测试:

    from timeit import Timer
    setup1 = '''import numpy as np
    a = np.array([])'''
    stmnt1 = 'np.append(a, 1)'
    t1 = Timer(stmnt1, setup1)
    
    setup2 = 'l = list()'
    stmnt2 = 'l.append(1)'
    t2 = Timer(stmnt2, setup2)
    
    print('appending to empty list:')
    print(t1.repeat(number=1000))
    print(t2.repeat(number=1000))
    
    setup1 = '''import numpy as np
    a = np.array(range(999999))'''
    stmnt1 = 'np.append(a, 1)'
    t1 = Timer(stmnt1, setup1)
    
    setup2 = 'l = [x for x in xrange(999999)]'
    stmnt2 = 'l.append(1)'
    t2 = Timer(stmnt2, setup2)
    
    print('appending to large list:')
    print(t1.repeat(number=1000))
    print(t2.repeat(number=1000))
    

    结果:

    appending to empty list:
    [0.008171333983972538, 0.0076482562944814175, 0.007862921943675175]
    [0.00015624398517267296, 0.0001191077336243837, 0.000118654852507942]
    appending to large list:
    [2.8521017080411304, 2.8518707386717446, 2.8022625940577477]
    [0.0001643958452675065, 0.00017888804099541744, 0.00016711313196715594]
    

    【讨论】:

      【解决方案4】:

      我不认为 numpy 很慢,因为它必须考虑到编写和调试所需的时间。程序越长,就越难发现问题或添加新功能(程序员时间)。 因此,使用更高级别的语言可以在同等智能时间和技能的情况下创建复杂且可能更高效的程序。

      无论如何,一些有趣的优化工具是:

      -Psyco 是一种 JIT(即时,“实时”),它在运行时优化代码。

      -Numexpr,并行化是加快程序执行速度的好方法,前提是可充分分离。

      -weave 是 NumPy 中的一个模块,用来沟通 Python 和 C。它的一个功能是 blitz,它取一行 Python,透明地翻译 C,每次调用执行优化版。进行第一次转换需要大约一秒钟,但更高的速度通常可以满足上述所有要求。它不像 Numexpr 或 Psyco 字节码,也不是像 NumPy 那样的接口 C,而是您自己的函数,直接用 C 编写并完全编译和优化。

      【讨论】:

        猜你喜欢
        • 2017-10-26
        • 2018-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-12
        • 2012-10-14
        • 2011-03-14
        • 2014-05-29
        相关资源
        最近更新 更多