Python因为是解释执行的,所以其效率远不如C语音。但是一些库的底层是使用了C语音编写的。所以一个小的技巧就是尽可能使用库函数,而不是使用自己的函数。
比如遍历numpy的数组,最好的方法就是使用numpy提供的方法,而不是自己编写遍历过程。假设需求是统计数组中出现的数值进行统计。数组存储的是整数,数值在0~255之间(图像的灰度图就是这种类型的数组)。
分别使用自己编写的遍历方法以及numpy的方法,其执行效率的差别是5倍以上。代码如下:
#coding:utf8
import numpy as np
import cProfile
def numpy_method(data_in):
data = np.zeros(256,dtype=np.uint32)
for v in range(256):
data[v] = np.sum(data_in==v)
#return data
def self_method(data_in):
rows, cols = data_in.shape
data = np.zeros([256], np.uint32)
for r in range(rows):
for c in range(cols):
data[data_in[r][c]] += 1
#return data
data_in = np.random.randint(low=0,high=255,size=(200,200),dtype=np.uint16)
cProfile.run("numpy_method(data_in)")
cProfile.run("self_method(data_in)")
结果如下:
2309 function calls in 0.017 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
256 0.000 0.000 0.012 0.000 <__array_function__ internals>:2(sum)
1 0.000 0.000 0.017 0.017 <string>:1(<module>)
256 0.000 0.000 0.000 0.000 fromnumeric.py:2100(_sum_dispatcher)
256 0.000 0.000 0.012 0.000 fromnumeric.py:2105(sum)
256 0.000 0.000 0.011 0.000 fromnumeric.py:70(_wrapreduction)
256 0.000 0.000 0.000 0.000 fromnumeric.py:71(<dictcomp>)
1 0.005 0.005 0.017 0.017 perf.py:5(numpy_method)
1 0.000 0.000 0.017 0.017 {built-in method builtins.exec}
256 0.000 0.000 0.000 0.000 {built-in method builtins.isinstance}
256 0.000 0.000 0.012 0.000 {built-in method numpy.core._multiarray_umath.implement_array_function}
1 0.000 0.000 0.000 0.000 {built-in method numpy.zeros}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
256 0.000 0.000 0.000 0.000 {method 'items' of 'dict' objects}
256 0.011 0.000 0.011 0.000 {method 'reduce' of 'numpy.ufunc' objects}
5 function calls in 0.096 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.096 0.096 <string>:1(<module>)
1 0.096 0.096 0.096 0.096 perf.py:11(self_method)
1 0.000 0.000 0.096 0.096 {built-in method builtins.exec}
1 0.000 0.000 0.000 0.000 {built-in method numpy.zeros}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
第一个是numpy执行的时间,0.017秒,第二个是自定义遍历的时间是0.096秒。可以方向使用库函数的调用函数次数增多,但是耗时少。自定义方法调用函数少但是耗时多。因此要尽量使用库函数,尤其项numpy、tensorflow这样的库函数,因为背后支撑的是c、GPU,会极大的提高性能。