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 相关文章推荐
python海龟绘图实例教程
Jul 24 Python
跟老齐学Python之有点简约的元组
Sep 24 Python
使用python中的in ,not in来检查元素是不是在列表中的方法
Jul 06 Python
学生信息管理系统Python面向对象版
Jan 30 Python
Django REST framework内置路由用法
Jul 26 Python
Jupyter Notebook打开任意文件夹操作
Apr 14 Python
使用python-Jenkins批量创建及修改jobs操作
May 12 Python
Django ORM filter() 的运用详解
May 14 Python
Python分类测试代码实例汇总
Jul 23 Python
如何实现一个python函数装饰器(Decorator)
Oct 12 Python
PyCharm 2020.2.2 x64 下载并安装的详细教程
Oct 15 Python
Python 详解通过Scrapy框架实现爬取百度新冠疫情数据流程
Nov 11 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
使用eAccelerator加密PHP程序
2008/10/03 PHP
PHP数组循环操作详细介绍 附实例代码
2013/02/03 PHP
php模仿asp Application对象在线人数统计实现方法
2015/01/04 PHP
PHP框架性能测试报告
2016/05/08 PHP
JS 文件传参及处理技巧分析
2010/05/13 Javascript
js获取通过ajax返回的map型的JSONArray的方法
2014/01/09 Javascript
js使用栈来实现10进制转8进制与取除数及余数
2014/06/11 Javascript
Express.JS使用详解
2014/07/17 Javascript
5个可以帮你理解JavaScript核心闭包和作用域的小例子
2014/10/08 Javascript
关于javascript模块加载技术的一些思考
2014/11/28 Javascript
JQuery中$.each 和$(selector).each()的区别详解
2015/03/13 Javascript
JQuery实现样式设置、追加、移除与切换的方法
2015/06/11 Javascript
js实现鼠标拖动功能
2017/03/20 Javascript
vue-cli2.0转3.0之项目搭建的详细步骤
2018/12/11 Javascript
redux.js详解及基本使用
2019/05/24 Javascript
微信小程序文章详情页跳转案例详解
2019/07/09 Javascript
解决layui弹框失效的问题
2019/09/09 Javascript
JQuery事件委托(适用于给动态生成的脚本元素添加事件)
2020/02/01 jQuery
[01:38]DOTA2辉夜杯 欢乐的观众现场采访
2015/12/26 DOTA
django+xadmin+djcelery实现后台管理定时任务
2018/08/14 Python
python爬虫URL重试机制的实现方法(python2.7以及python3.5)
2018/12/18 Python
python 已知平行四边形三个点,求第四个点的案例
2020/04/12 Python
python logging通过json文件配置的步骤
2020/04/27 Python
python爬虫看看虎牙女主播中谁最“顶”步骤详解
2020/12/01 Python
HTML5 的新的表单元素(datalist/keygen/output)使用介绍
2013/07/19 HTML / CSS
html5通过canvas实现刮刮卡效果示例分享
2014/01/27 HTML / CSS
HTML5 画布canvas使用方法
2016/03/18 HTML / CSS
美国求婚钻戒网站:Super Jeweler
2016/08/27 全球购物
Speedo速比涛法国官方网站:泳衣、泳镜、泳帽、泳裤
2019/07/30 全球购物
师范教师毕业鉴定
2014/01/13 职场文书
家长对小学生的评语
2014/01/28 职场文书
化工工艺设计求职信
2014/06/25 职场文书
教师师德考核自我评价
2014/09/13 职场文书
高三毕业感言
2015/07/30 职场文书
安全教育主题班会总结
2015/08/14 职场文书
详解Mysql事务并发(脏读、不可重复读、幻读)
2022/04/29 MySQL