1. 程式人生 > >python numpy numba 計算速度對比

python numpy numba 計算速度對比

#!/usr/bin/python
# -*- coding: utf-8 -*-
#####################################
# File name : test.py
# Create date : 2019-01-05 17:11
# Modified date : 2019-01-05 17:59
# Author : DARREN
# Describe : not set
# Email : [email protected]
#####################################
from __future__ import division
from
__future__ import print_function import numpy as np from timeit import Timer from numba import jit def python_list(n): a = range(n) b = range(n) c = [] for i in range(len(a)): a[i] = i ** 2 b[i] = i ** 3 c.append(a[i] + b[i]) return c @jit def python_list_with_numba
(n): # a = range(n) # b = range(n) # c = [] # for i in range(len(a)): # a[i] = i ** 2 # b[i] = i ** 3 # c.append(a[i] + b[i]) # return c return python_list(n) def numpy_vector(n): x = np.arange(n) y = np.arange(n) z = x**2 + y**3 return z @jit def numpy_vector_with_numba
(n): # x = np.arange(n) # y = np.arange(n) # z = x**2 + y**3 # return z return numpy_vector(n) if __name__ == '__main__': t1 = Timer('python_list(1000000)','from __main__ import python_list') t2 = Timer('python_list_with_numba(1000000)','from __main__ import python_list_with_numba') t3 = Timer('python_list_with_numba(1000000)','from __main__ import python_list_with_numba') t4 = Timer('numpy_vector(1000000)','from __main__ import numpy_vector') t5 = Timer('numpy_vector_with_numba(1000000)','from __main__ import numpy_vector_with_numba') t6 = Timer('numpy_vector_with_numba(1000000)','from __main__ import numpy_vector_with_numba') take_time1 = t1.timeit(50) take_time2 = t2.timeit(50) take_time3 = t3.timeit(50) take_time4 = t4.timeit(50) take_time5 = t5.timeit(50) take_time6 = t6.timeit(50) print("python list:%s" % take_time1) print("python list with numba comp:%s" % take_time2) print("python list with numba after comp:%s" % take_time3) print("numpy vector:%s" % take_time4) print("numpy vector with numba comp:%s" % take_time5) print("numpy vector with numba after comp:%s" % take_time6)

output

python list:8.37137699127
python list with numba comp:8.26541399956
python list with numba after comp:8.33281493187
numpy vector:0.529839992523
numpy vector with numba comp:0.539204835892
numpy vector with numba after comp:0.524770021439

好像呼叫函式對與 numba來說是有有影響的.呼叫函式的話numba 就起不到加速的效果了.下面去掉函式呼叫

#!/usr/bin/python
# -*- coding: utf-8 -*-
#####################################
# File name : test.py
# Create date : 2019-01-05 17:11
# Modified date : 2019-01-05 18:05
# Author : DARREN
# Describe : not set
# Email : [email protected]
#####################################
from __future__ import division
from __future__ import print_function

import numpy as np
from timeit import Timer
from numba import jit

def python_list(n):
    a = range(n)
    b = range(n)
    c = []
    for i in range(len(a)):
        a[i] = i ** 2
        b[i] = i ** 3
        c.append(a[i] + b[i])
    return c

@jit
def python_list_with_numba(n):
    a = range(n)
    b = range(n)
    c = []
    for i in range(len(a)):
        a[i] = i ** 2
        b[i] = i ** 3
        c.append(a[i] + b[i])
    return c

def numpy_vector(n):
    x = np.arange(n)
    y = np.arange(n)
    z = x**2 + y**3
    return z

@jit
def numpy_vector_with_numba(n):
    x = np.arange(n)
    y = np.arange(n)
    z = x**2 + y**3
    return z


if __name__ == '__main__':
    t1 = Timer('python_list(1000000)','from __main__ import python_list')
    t2 = Timer('python_list_with_numba(1000000)','from __main__ import python_list_with_numba')
    t3 = Timer('python_list_with_numba(1000000)','from __main__ import python_list_with_numba')
    t4 = Timer('numpy_vector(1000000)','from __main__ import numpy_vector')
    t5 = Timer('numpy_vector_with_numba(1000000)','from __main__ import numpy_vector_with_numba')
    t6 = Timer('numpy_vector_with_numba(1000000)','from __main__ import numpy_vector_with_numba')

    take_time1 = t1.timeit(50)
    take_time2 = t2.timeit(50)
    take_time3 = t3.timeit(50)
    take_time4 = t4.timeit(50)
    take_time5 = t5.timeit(50)
    take_time6 = t6.timeit(50)

    print("python list:%s" % take_time1)
    print("python list with numba comp:%s" % take_time2)
    print("python list with numba after comp:%s" % take_time3)
    print("numpy vector:%s" % take_time4)
    print("numpy vector with numba comp:%s" % take_time5)
    print("numpy vector with numba after comp:%s" % take_time6)

output

python list:8.16710710526
python list with numba comp:9.53106093407
python list with numba after comp:9.40612602234
numpy vector:0.188210964203
numpy vector with numba comp:0.314162015915
numpy vector with numba after comp:0.0830471515656

numpy在計算上比python 要快.加上numba後numpy似乎可以提高1倍的速度.
numba編譯的那次速度是比較慢的.

#!/usr/bin/python
# -*- coding: utf-8 -*-
#####################################
# File name : test.py
# Create date : 2019-01-05 17:11
# Modified date : 2019-01-05 21:27
# Author : DARREN
# Describe : not set
# Email : [email protected]
#####################################
from __future__ import division
from __future__ import print_function

import numpy as np
from timeit import Timer
from numba import jit
from numba import njit

def python_list(n):
    a = range(n)
    b = range(n)
    c = []
    for i in range(len(a)):
        a[i] = i ** 2
        b[i] = i ** 3
        c.append(a[i] + b[i])
    return c

@jit
def python_list_with_numba(n):
    a = range(n)
    b = range(n)
    c = []
    for i in range(len(a)):
        a[i] = i ** 2
        b[i] = i ** 3
        c.append(a[i] + b[i])
    return c

def numpy_vector(n):
    x = np.arange(n)
    y = np.arange(n)
    z = x**2 + y**3
    return z

@jit
def numpy_vector_with_numba(n):
    x = np.arange(n)
    y = np.arange(n)
    z = x**2 + y**3
    return z

@njit(fastmath=True)
def numpy_vector_with_numba_fast(n):
    x = np.arange(n)
    y = np.arange(n)
    z = x**2 + y**3
    return z

@njit(parallel=True)
def numpy_vector_with_numba_parallel(n):
    x = np.arange(n)
    y = np.arange(n)
    z = x**2 + y**3
    return z

@njit(fastmath=True, parallel=True)
def numpy_vector_with_numba_fast_parallel(n):
    x = np.arange(n)
    y = np.arange(n)
    z = x**2 + y**3
    return z


if __name__ == '__main__':
    t1 = Timer('python_list(1000000)','from __main__ import python_list')
    t2 = Timer('python_list_with_numba(1000000)','from __main__ import python_list_with_numba')
    t3 = Timer('python_list_with_numba(1000000)','from __main__ import python_list_with_numba')
    t4 = Timer('numpy_vector(1000000)','from __main__ import numpy_vector')
    t5 = Timer('numpy_vector_with_numba(1000000)','from __main__ import numpy_vector_with_numba')
    t6 = Timer('numpy_vector_with_numba(1000000)','from __main__ import numpy_vector_with_numba')
    t7 = Timer('numpy_vector_with_numba_fast(1000000)','from __main__ import numpy_vector_with_numba_fast')
    t8 = Timer('numpy_vector_with_numba_fast(1000000)','from __main__ import numpy_vector_with_numba_fast')

    t9 = Timer('numpy_vector_with_numba_parallel(1000000)','from __main__ import numpy_vector_with_numba_parallel')
    t10 = Timer('numpy_vector_with_numba_parallel(1000000)','from __main__ import numpy_vector_with_numba_parallel')

    t11 = Timer('numpy_vector_with_numba_fast_parallel(1000000)','from __main__ import numpy_vector_with_numba_fast_parallel')
    t12 = Timer('numpy_vector_with_numba_fast_parallel(1000000)','from __main__ import numpy_vector_with_numba_fast_parallel')

    take_time1 = t1.timeit(50)
    take_time2 = t2.timeit(50)
    take_time3 = t3.timeit(50)
    take_time4 = t4.timeit(50)
    take_time5 = t5.timeit(50)
    take_time6 = t6.timeit(50)
    take_time7 = t7.timeit(50)
    take_time8 = t8.timeit(50)
    take_time9 = t9.timeit(50)
    take_time10 = t10.timeit(50)
    take_time11 = t11.timeit(50)
    take_time12 = t12.timeit(50)

    print("python_list:%s" % take_time1)
    print("python_list_with_numba compile:%s" % take_time2)
    print("python_list_with_numba after compile:%s" % take_time3)
    print("numpy_vector:%s" % take_time4)
    print("numpy_vector_with_numba compile:%s" % take_time5)
    print("numpy_vector_with_numba after compile:%s" % take_time6)
    print("numpy_vector_with_numba_fast compile:%s" % take_time7)
    print("numpy_vector_with_numba_fast after compile:%s" % take_time8)
    print("numpy_vector_with_numba_parallel compile:%s" % take_time9)
    print("numpy_vector_with_numba_parallel after compile:%s" % take_time10)
    print("numpy_vector_with_numba_fast_parallel compile:%s" % take_time11)
    print("numpy_vector_with_numba_fast_parallel after compile:%s" % take_time12)

output

python_list:8.22160506248
python_list_with_numba compile:9.52428817749
python_list_with_numba after compile:9.4302740097
numpy_vector:0.18684220314
numpy_vector_with_numba compile:0.313122034073
numpy_vector_with_numba after compile:0.0834867954254
numpy_vector_with_numba_fast compile:0.166754961014
numpy_vector_with_numba_fast after compile:0.0827031135559
numpy_vector_with_numba_parallel compile:0.353137016296
numpy_vector_with_numba_parallel after compile:0.0367288589478
numpy_vector_with_numba_fast_parallel compile:0.359938144684
numpy_vector_with_numba_fast_parallel after compile:0.0356090068817

加上parallel 能夠提速6倍.看起來確實加速了.

下面測試下矩陣相乘 是否能被加速

#!/usr/bin/python
# -*- coding: utf-8 -*-
#####################################
# File name : test.py
# Create date : 2019-01-05 17:11
# Modified date : 2019-01-05 22:22
# Author : DARREN
# Describe : not set
# Email : [email protected]
#####################################
from __future__ import division
from __future__ import print_function

import numpy as np
from timeit import Timer
from numba import jit
from numba import njit

def dot(x,y):
    z = np.dot(x,y)
    return z

@jit
def dot_numba(x,y):
    z = np.dot(x,y)
    return z

@njit(fastmath=True)
def dot_numba_fast(x,y):
    z = np.dot(x,y)
    return z

@njit(parallel=True)
def dot_numba_parallel(x,y):
    z = np.dot(x,y)
    return z

@njit(fastmath=True, parallel=True)
def dot_numba_fast_parallel(x,y):
    z = np.dot(x,y)
    return z

if __name__ == '__main__':

    x = np.random.randn(100,100)
    y = np.random.randn(100,100)

    t1 = Timer('dot(x,y)','from __main__ import dot,x,y')
    t2 = Timer('dot_numba(x,y)','from __main__ import dot_numba,x,y')
    t3 = Timer('dot_numba(x,y)','from __main__ import dot_numba,x,y')
    t4 = Timer('dot_numba_fast(x,y)','from __main__ import dot_numba_fast,x,y')
    t5 = Timer('dot_numba_fast(x,y)','from __main__ import dot_numba_fast,x,y')

    t6 = Timer('dot_numba_parallel(x,y)','from __main__ import dot_numba_parallel,x,y')
    t7 = Timer('dot_numba_parallel(x,y)','from __main__ import dot_numba_parallel,x,y')

    t8 = Timer('dot_numba_fast_parallel(x,y)','from __main__ import dot_numba_fast_parallel,x,y')
    t9 = Timer('dot_numba_fast_parallel(x,y)','from __main__ import dot_numba_fast_parallel,x,y')

    take_time1 = t1.timeit(90)
    take_time2 = t2.timeit(90)
    take_time3 = t3.timeit(90)
    take_time4 = t4.timeit(90)
    take_time5 = t5.timeit(90)
    take_time6 = t6.timeit(90)
    take_time7 = t7.timeit(90)
    take_time8 = t8.timeit(90)
    take_time9 = t9.timeit(90)

    print("dot:%s" % take_time1)
    print("dot_numba compilation:%s" % take_time2)
    print("dot_numba after compilation:%s" % take_time3)
    print("dot_numba_fast compilation:%s" % take_time4)
    print("dot_numba_fast after compilation:%s" % take_time5)
    print("dot_numba_parallel compilation:%s" % take_time6)
    print("dot_numba_parallel after compilation:%s" % take_time7)
    print("dot_numba_fast_parallel compilation:%s" % take_time8)
    print("dot_numba_fast_parallel after compilation:%s" % take_time9)

output

dot:0.0045690536499
dot_numba compilation:0.161776065826
dot_numba after compilation:0.00354194641113
dot_numba_fast compilation:0.0609059333801
dot_numba_fast after compilation:0.00446605682373
dot_numba_parallel compilation:0.0760118961334
dot_numba_parallel after compilation:0.00450396537781
dot_numba_fast_parallel compilation:0.0754170417786
dot_numba_fast_parallel after compilation:0.00403594970703

能夠看到編譯的時候會更慢,編譯後的numba也不比numpy快.
下面把矩陣變大看下效果

#!/usr/bin/python
# -*- coding: utf-8 -*-
#####################################
# File name : test.py
# Create date : 2019-01-05 17:11
# Modified date : 2019-01-05 22:26
# Author : DARREN
# Describe : not set
# Email : [email protected]
#####################################
from __future__ import division
from __future__ import print_function

import numpy as np
from timeit import Timer
from numba import jit
from numba import njit

def dot(x,y):
    z = np.dot(x,y)
    return z

@jit
def dot_numba(x,y):
    z = np.dot(x,y)
    return z

@njit(fastmath=True)
def dot_numba_fast(x,y):
    z = np.dot(x,y)
    return z

@njit(parallel=True)
def dot_numba_parallel(x,y):
    z = np.dot(x,y)
    return z

@njit(fastmath=True, parallel=True)
def dot_numba_fast_parallel(x,y):
    z = np.dot(x,y)
    return z

if __name__ == '__main__':

    x = np.random.randn(1000,1000)
    y = np.random.randn(1000,1000)

    t1 = Timer('dot(x,y)','from __main__ import dot,x,y')
    t2 = Timer('dot_numba(x,y)','from __main__ import dot_numba,x,y')
    t3 = Timer('dot_numba(x,y)','from __main__ import dot_numba,x,y')
    t4 = Timer('dot_numba_fast(x,y)','from __main__ import dot_numba_fast,x,y')
    t5 = Timer('dot_numba_fast(x,y)','from __main__ import dot_numba_fast,x,y')

    t6 = Timer('dot_numba_parallel(x,y)','from __main__ import dot_numba_parallel,x,y')
    t7 = Timer('dot_numba_parallel(x,y)','from __main__ import dot_numba_parallel,x,y')

    t8 = Timer('dot_numba_fast_parallel(x,y)','from __main__ import dot_numba_fast_parallel,x,y')
    t9 = Timer('dot_numba_fast_parallel(x,y)','from __main__ import dot_numba_fast_parallel,x,y')

    take_time1 = t1.timeit(90)
    take_time2 = t2.timeit(90)
    take_time3 = t3.timeit(90)
    take_time4 = t4.timeit(90)
    take_time5 = t5.timeit(90)
    take_time6 = t6.timeit(90)
    take_time7 = t7.timeit(90)
    take_time8 =