python 性能优化方法小结


Posted in Python onMarch 31, 2017

提高性能有如下方法

1、Cython,用于合并python和c语言静态编译泛型

2、IPython.parallel,用于在本地或者集群上并行执行代码

3、numexpr,用于快速数值运算

4、multiprocessing,python内建的并行处理模块

5、Numba,用于为cpu动态编译python代码

6、NumbaPro,用于为多核cpu和gpu动态编译python代码

为了验证相同算法在上面不同实现上的的性能差异,我们先定义一个测试性能的函数

def perf_comp_data(func_list, data_list, rep=3, number=1): 
  '''Function to compare the performance of different functions. 
  Parameters 
  func_list : list 
  list with function names as strings

  data_list : list 
  list with data set names as strings 

  rep : int 
  number of repetitions of the whole comparison 
  number : int 
  number ofexecutions for every function 
  '''
  from timeit import repeat 
  res_list = {} 
  for name in enumerate(func_list): 
    stmt = name[1] + '(' + data_list[name[0]] + ')' 
    setup = "from __main__ import " + name[1] + ','+ data_list[name[0]] 
    results = repeat(stmt=stmt, setup=setup, repeat=rep, number=number) 
    res_list[name[1]] = sum(results) / rep
  res_sort = sorted(res_list.items(), key = lambda item : item[1])
  for item in res_sort: 
    rel = item[1] / res_sort[0][1]
    print ('function: ' + item[0] + ', av. time sec: %9.5f,  ' % item[1] + 'relative: %6.1f' % rel)

定义执行的算法如下

from math import * 
def f(x): 
  return abs(cos(x)) ** 0.5 + sin(2 + 3 * x)

对应的数学公式是

python 性能优化方法小结

生成数据如下

i=500000
a_py = range(i)

第一个实现f1是在内部循环执行f函数,然后将每次的计算结果添加到列表中,实现如下

def f1(a): 
  res = [] 
  for x in a: 
    res.append(f(x)) 
  return res

当然实现这种方案的方法不止一种,可以使用迭代器或eval函数,我自己加入了使用生成器和map方法的测试,发现结果有明显差距,不知道是否科学:

迭代器实现

def f2(a): 
  return [f(x) for x in a]

eval实现

def f3(a): 
  ex = 'abs(cos(x)) **0.5+ sin(2 + 3 * x)' 
  return [eval(ex) for x in a]

生成器实现

def f7(a): 
  return (f(x) for x in a)

map实现

def f8(a): 
  return map(f, a)

接下来是使用numpy的narray结构的几种实现

import numpy as np 
a_np = np.arange(i) 

def f4(a): 
  return (np.abs(np.cos(a)) ** 0.5 + np.sin(2 + 3 * a))

import numexpr as ne

def f5(a): 
  ex = 'abs(cos(a)) ** 0.5 + sin( 2 + 3 * a)' 
  ne.set_num_threads(1) 
  return ne.evaluate(ex)

def f6(a): 
  ex = 'abs(cos(a)) ** 0.5 + sin(2 + 3 * a)' 
  ne.set_num_threads(2) 
  return ne.evaluate(ex)

上面的f5和f6只是使用的处理器个数不同,可以根据自己电脑cpu的数目进行修改,也不是越大越好

下面进行测试

func_list = ['f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8'] 
data_list = ['a_py', 'a_py', 'a_py', 'a_np', 'a_np', 'a_np', 'a_py', 'a_py']
perf_comp_data(func_list, data_list)

测试结果如下

function: f8, av. time sec:  0.00000,  relative:  1.0
function: f7, av. time sec:  0.00001,  relative:  1.7
function: f6, av. time sec:  0.03787,  relative: 11982.7
function: f5, av. time sec:  0.05838,  relative: 18472.4
function: f4, av. time sec:  0.09711,  relative: 30726.8
function: f2, av. time sec:  0.82343,  relative: 260537.0
function: f1, av. time sec:  0.92557,  relative: 292855.2
function: f3, av. time sec: 32.80889,  relative: 10380938.6

发现f8的时间最短,调大一下时间精度再测一次

function: f8, av. time sec: 0.000002483,  relative:  1.0
function: f7, av. time sec: 0.000004741,  relative:  1.9
function: f5, av. time sec: 0.028068110,  relative: 11303.0
function: f6, av. time sec: 0.031389788,  relative: 12640.6
function: f4, av. time sec: 0.053619114,  relative: 21592.4
function: f1, av. time sec: 0.852619225,  relative: 343348.7
function: f2, av. time sec: 1.009691877,  relative: 406601.7
function: f3, av. time sec: 26.035869787,  relative: 10484613.6

发现使用map的性能最高,生成器次之,其他方法的性能就差的很远了。但是使用narray数据的在一个数量级,使用python的list数据又在一个数量级。生成器的原理是并没有生成一个完整的列表,而是在内部维护一个next函数,通过一边循环迭代一遍生成下个元素的方法的实现的,所以他既不用在执行时遍历整个循环,也不用分配整个空间,它花费的时间和空间跟列表的大小是没有关系的,map与之类似,而其他实现都是跟列表大小有关系的。

内存布局

numpy的ndarray构造函数形式为

np.zeros(shape, dtype=float, order='C')

np.array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0)

shape或object定义了数组的大小或是引用了另一个一个数组

dtype用于定于元素的数据类型,可以是int8,int32,float8,float64等等

order定义了元素在内存中的存储顺序,c表示行优先,F表示列优先

下面来比较一下内存布局在数组很大时的差异,先构造同样的的基于C和基于F的数组,代码如下:

x = np.random.standard_normal(( 3, 1500000))
c = np.array(x, order='C') 
f = np.array(x, order='F')

下面来测试性能

%timeit c.sum(axis=0)
%timeit c.std(axis=0)
%timeit f.sum(axis=0)
%timeit f.std(axis=0)
%timeit c.sum(axis=1)
%timeit c.std(axis=1)
%timeit f.sum(axis=1)
%timeit f.std(axis=1)

输出如下

loops, best of 3: 12.1 ms per loop
loops, best of 3: 83.3 ms per loop
loops, best of 3: 70.2 ms per loop
loop, best of 3: 235 ms per loop
loops, best of 3: 7.11 ms per loop
loops, best of 3: 37.2 ms per loop
loops, best of 3: 54.7 ms per loop
loops, best of 3: 193 ms per loop

可知,C内存布局要优于F内存布局

并行计算

未完,待续。。。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Python 相关文章推荐
Python3.X 线程中信号量的使用方法示例
Jul 24 Python
100行Python代码实现自动抢火车票(附源码)
Jan 11 Python
Python 实现两个列表里元素对应相乘的方法
Nov 14 Python
python 通过SSHTunnelForwarder隧道连接redis的方法
Feb 19 Python
pyqt5 tablewidget 利用线程动态刷新数据的方法
Jun 17 Python
Pandas之DataFrame对象的列和索引之间的转化
Jun 25 Python
python使用 request 发送表单数据操作示例
Sep 25 Python
pytorch 图像预处理之减去均值,除以方差的实例
Jan 02 Python
Tensorflow安装问题: Could not find a version that satisfies the requirement tensorflow
Apr 20 Python
打印tensorflow恢复模型中所有变量与操作节点方式
May 26 Python
Python可以实现栈的结构吗
May 27 Python
python 窃取摄像头照片的实现示例
Jan 08 Python
Python+Selenium自动化实现分页(pagination)处理
Mar 31 #Python
pygame加载中文名mp3文件出现error
Mar 31 #Python
Python自动发邮件脚本
Mar 31 #Python
Python中查看文件名和文件路径
Mar 31 #Python
使用python遍历指定城市的一周气温
Mar 31 #Python
python网络编程调用recv函数完整接收数据的三种方法
Mar 31 #Python
Python爬取网易云音乐热门评论
Mar 31 #Python
You might like
Netflix将与CLAMP、乙一以及冲方丁等6名知名制作人合伙展开原创动画计划!
2020/03/06 日漫
多重?l件?合查?(二)
2006/10/09 PHP
使用php实现从身份证中提取生日
2016/05/09 PHP
加载jQuery后$冲突的解决办法
2010/07/09 Javascript
遍历jquery对象的代码分享
2011/11/02 Javascript
jquery控制左右箭头滚动图片列表的实例
2013/05/20 Javascript
js定时器(执行一次、重复执行)
2014/03/07 Javascript
js判断当页面无法回退时关闭网页否则就history.go(-1)
2014/08/07 Javascript
Javascript 中创建自定义对象的方法汇总
2014/12/04 Javascript
jQuery简单几行代码实现tab切换
2015/03/10 Javascript
jQuery实现浮动层随浏览器滚动条滚动的方法
2015/09/22 Javascript
JS+CSS实现另类带提示效果的竖向导航菜单
2015/10/15 Javascript
JavaScript获取对象在页面中位置坐标的方法
2016/02/03 Javascript
jQuery获得字体颜色16位码的方法
2016/02/20 Javascript
js改变透明度实现轮播图的算法
2020/08/24 Javascript
用file标签实现多图文件上传预览
2017/02/14 Javascript
Javascript实现时间倒计时效果
2017/07/15 Javascript
分分钟学会vue中vuex的应用(入门教程)
2017/09/14 Javascript
通过函数作用域和块级作用域看javascript的作用域链
2018/08/05 Javascript
vue项目前端埋点的实现
2019/03/06 Javascript
jQuery实现图片下载代码
2019/07/18 jQuery
关于在LayUI中使用AJAX提交巨坑记录
2019/10/25 Javascript
Python列表list内建函数用法实例分析【insert、remove、index、pop等】
2017/07/24 Python
详解Python中where()函数的用法
2018/03/27 Python
python判断设备是否联网的方法
2018/06/29 Python
python实现两个经纬度点之间的距离和方位角的方法
2019/07/05 Python
Pycharm+django2.2+python3.6+MySQL实现简单的考试报名系统
2019/09/05 Python
python保留小数位的三种实现方法
2020/01/07 Python
微信小程序之html5 canvas绘图并保存到系统相册
2019/06/20 HTML / CSS
超30万乐谱下载:Musicnotes.com
2016/09/24 全球购物
日本著名的服饰鞋帽综合类购物网站:MAGASEEK
2019/01/09 全球购物
说出ArrayList,Vector, LinkedList的存储性能和特性
2015/01/04 面试题
移动通信行业实习自我鉴定
2013/09/28 职场文书
装配出错检讨书
2014/09/23 职场文书
疾病证明书
2015/06/19 职场文书
Python OpenCV实现传统图片格式与base64转换
2021/06/13 Python