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中的数学运算操作符使用进阶
Jun 20 Python
python读取图片的方式,以及将图片以三维数组的形式输出方法
Jul 03 Python
Python面向对象封装操作案例详解
Dec 31 Python
python 解决flask 图片在线浏览或者直接下载的问题
Jan 09 Python
Python 格式化输出_String Formatting_控制小数点位数的实例详解
Feb 04 Python
python集成开发环境配置(pycharm)
Feb 14 Python
pandas中的ExcelWriter和ExcelFile的实现方法
Apr 24 Python
python模块如何查看
Jun 16 Python
详解python with 上下文管理器
Sep 02 Python
python 实现控制鼠标键盘
Nov 27 Python
python 装饰器重要在哪
Feb 14 Python
Python利用zhdate模块实现农历日期处理
Mar 31 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
短波问题解答
2021/02/28 无线电
php对数组排序的简单实例
2013/12/25 PHP
PHP 面向对象程序设计(oop)学习笔记(三) - 单例模式和工厂模式
2014/06/12 PHP
thinkphp微信开之安全模式消息加密解密不成功的解决办法
2015/12/02 PHP
对setInterval在火狐和chrome切换标签产生奇怪的效果之探索,与解决方案!
2011/10/29 Javascript
判断一个变量是数组Array类型的方法
2013/09/16 Javascript
node中socket.io的事件使用详解
2014/12/15 Javascript
JavaScript将一个数组插入到另一个数组的方法
2015/03/19 Javascript
jQuery实现鼠标选文字发新浪微博的方法
2016/04/02 Javascript
Vue.js每天必学之指令系统与自定义指令
2016/09/07 Javascript
前端跨域的几种解决方式总结(推荐)
2017/08/16 Javascript
webpack多入口文件页面打包配置详解
2018/01/09 Javascript
使用veloticy-ui生成文字动画效果
2018/02/08 Javascript
微信小程序开发之改变data中数组或对象的某一属性值
2018/07/05 Javascript
详解vue填坑之解决部分浏览器不支持pushState方法
2018/07/12 Javascript
[01:21]2018DOTA2亚洲邀请赛4.5采访 打DOTA2也能有女朋友?
2018/04/06 DOTA
深入Python函数编程的一些特性
2015/04/13 Python
在Python中使用模块的教程
2015/04/27 Python
深入讲解Python编程中的字符串
2015/10/14 Python
Python SQLite3数据库日期与时间常见函数用法分析
2017/08/14 Python
Python设计模式之观察者模式原理与用法详解
2019/01/16 Python
Python+OpenCV图片局部区域像素值处理详解
2019/01/23 Python
将python安装信息加入注册表的示例
2019/11/20 Python
创建Shapefile文件并写入数据的例子
2019/11/26 Python
Python3+SQLAlchemy+Sqlite3实现ORM教程
2021/02/16 Python
美国汽配连锁巨头Pep Boys官网:轮胎更换、汽车维修服务和汽车零部件
2017/01/14 全球购物
Expedia印度尼西亚站:预订酒店、廉价航班和度假套餐
2018/01/31 全球购物
美国婴儿用品及配件购买网站:Munchkin
2019/04/03 全球购物
Emma Bridgewater官网:英国餐具制造商
2019/11/24 全球购物
大学生个人简历中的自我评价
2013/12/27 职场文书
预备党员公开承诺书
2014/05/28 职场文书
消防标语大全
2014/06/07 职场文书
检讨书格式范文
2015/05/07 职场文书
2015年小学财务工作总结
2015/07/20 职场文书
如何书写你的职业生涯规划书?
2019/06/27 职场文书
ant design charts 获取后端接口数据展示
2022/05/25 Javascript