如何获得NumPy的调整为最佳性能能

from:.cn/archives/5
系统:Gentoo Linux (64bit, Kernel 3.7.1)配置:Intel(R) Core(TM) i7-2670QM在Gentoo中安装Numpy/Scipy非常简单,直接emerge就可以解决。但是默认链接的blas/lapack库性能非常差,在矩阵计算方面比MATLAB慢了不少。原因在于MATLAB使用的是高度优化的数值计算库Intel math kernel library (MKL)。最新的MKL库在science overlay中有,安装后通过eselect blas/lapack set可以将系统默认链接的库设定为MKL(如mkl64-int64-dynamic-openmp)。设定之后再emerge numpy就可使用链接MKL库的numpy,而且可以发现svd等常用矩阵计算函数的速度大大提升。可问题是scipy无法emerge通过,查看log发现scipy无法检测到-lblas,即它根本没有识别系统默认链接库的设置。science overlay中blas/lapack库及其相关包的安装向来十分纠结,因为这里面似乎还没有完善的链接管理。这些问题持续了至少一年,近来才发现(部分)解决途径。
我们改换策略,手工安装numpy。首先获取最新的numpy包:git clone git:///numpy/numpy.git numpy然后进入到根目录。我们需要进行一些配置才能使numpy用上安装好的MKL库。这部分可以参考Intel官网的一个教程:
/en-us/articles/numpyscipy-with-intel-mkl
首先在根目录中加入site.cfg文件:
[mkl]library_dirs = /opt/intel/mkl/composer_xe_2013/lib/intel64include_dirs = /opt/intel/mkl/includemkl_libs = mkl_rtlapack_libs =
这里library_dirs与include_dirs是MKL的相关路径,注意各Linux发行版有细微区别。接下来修改numpy/distutils/intelccompiler.py中的cc_exe:
self.cc_exe = 'icc -O3 -g -fPIC -fp-model strict -fomit-frame-pointer -openmp -xhost'
以及numpy/distutil/fcompiler/intel.py中ifort的参数(最新版numpy里已经设置好了)。最后回到根目录进行编译:
sudo python2.7 setup.py config --compiler=intelem --fcompiler=intelem build_clib --compiler=intelem --fcompiler=intelem build_ext --compiler=intelem --fcompiler=intelem install
因为使用的是64位系统,所以是intelem。由于用到了Intel的c与fortran编译器(这二者也能带来性能的提升),编译前需要预先安装icc以及ifc(直接emerge即可安装)。注意,上述命令只编译了python2.7版本的,而之后系统编译scipy还需要py3k版本,所以还需要用python3.2再编译一次,这样两种版本的numpy就都安装在了系统中。至此我们已经从源码安装了numpy,且让其链接上了最新的MKL库。现在产生了一个新的问题:使用emerge安装scipy等其他依赖numpy的包时系统会自动安装numpy,覆盖掉我们手工安装的numpy,这样就又回到了之前的老路子。这时Gentoo灵活的配置性就体现出来了,通过echo "dev-python/numpy-1.7.0" && /etc/portage/profile/package.provided我们可以告诉系统numpy的1.7.0版本已经手动安装好了,这样系统之后安装其他依赖包时就不会再动numpy了。当然,隔一段时间后numpy可能会发布新版本,这时更新系统会把已安装的numpy覆盖掉,所以要定期手动升级numpy。
上面这种方法的好处是最大程度保留了系统功能,让系统去自动处理尽量多的任务,留给我们的任务仅仅是每隔一段时间更新Numpy。使用python做普通科学计算,其性能主要由numpy决定,因此保证numpy的最优就足够。当然也可以手动编译所有python数值计算库,只是会在更新时多费些时间和精力。实际测试中,这种方法安装的numpy的速度稍快于MATLAB,不过numpy与scipy的自带测试并没有全部通过。这并不影响基本使用,因此我还未探究原因何在。
阅读(...) 评论()python 性能优化方法小结
投稿:sxyy
字体:[ ] 类型:转载 时间:
本文主要介绍了python 提高性能的方法。具有很好的参考价值,下面跟着小编一起来看下吧
提高性能有如下方法
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
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 *
return abs(cos(x)) ** 0.5 + sin(2 + 3 * x)
对应的数学公式是
生成数据如下
a_py = range(i)
第一个实现f1是在内部循环执行f函数,然后将每次的计算结果添加到列表中,实现如下
def f1(a):
for x in a:
res.append(f(x))
return res
当然实现这种方案的方法不止一种,可以使用迭代器或eval函数,我自己加入了使用生成器和map方法的测试,发现结果有明显差距,不知道是否科学:
迭代器实现
def f2(a):
return [f(x) for x in a]
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)
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:
function: f7, av. time sec:
function: f6, av. time sec:
relative: 11982.7
function: f5, av. time sec:
relative: 18472.4
function: f4, av. time sec:
relative: 30726.8
function: f2, av. time sec:
function: f1, av. time sec:
function: f3, av. time sec: 32.80889,
发现f8的时间最短,调大一下时间精度再测一次
function: f8, av. time sec: 0.,
function: f7, av. time sec: 0.,
function: f5, av. time sec: 0.,
relative: 11303.0
function: f6, av. time sec: 0.,
relative: 12640.6
function: f4, av. time sec: 0.,
relative: 21592.4
function: f1, av. time sec: 0.,
function: f2, av. time sec: 1.,
function: f3, av. time sec: 26.,
发现使用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内存布局
未完,待续。。。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持脚本之家!
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具违法和不良信息举报电话:183-
举报邮箱:
Copyright(C)2017 大不六文章网Python在科学计算中和C比较,性能差距大吗 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
已注册用户请 &
推荐学习书目
Python Sites
值得关注的项目
Python 编程
Python在科学计算中和C比较,性能差距大吗
05:27:09 +08:00 · 7695 次点击
之前很少使用python,想问下对于大量数据的科学计算,比如machine learning,V2EX里有人使用python来实现算法吗?python实现的程序执行速度和C实现,以及MATLAB实现的,有什么差距呢?另外numpy对于数组和矩阵的处理有MATLAB方便吗?谢啦。
第 1 条附言 &·&
14:44:53 +08:00
我理解楼下各位意思是python在科学计算中实际是属于胶水作用python调用的各种库都是用C实现的...我决定先不移植到python上了 把这个时间拿来用openmp实现下parallel computing
22 回复 &| &直到
08:00:00 +08:00
& & 05:37:11 +08:00
后端一般都是MP/MPI+C和Fortran
前端看到的多数是Python...
PS: CADD领域
& & 06:16:44 +08:00
估计还是 Matlab 处理矩阵运算厉害些。
代数相关的领域,用 SAGE 的人很多,这个完全是基于 Python 的, 可能有些关键部分用 C 优化过。
& & 06:20:03 +08:00
@ 你们是不是有C或Fortran实现的library 然后python只是用来调用那些API吗?
& & 06:54:00 +08:00
@ matlab对于循环处理太慢...
下了个SAGE看了下,他的优势是不是在于built-in functions?感觉性质和matlab等数学辅助工具一样吧
& & 07:03:55 +08:00
做machine learning如果你数据量大的话,也不需要并行计算,一般的瓶颈在磁盘IO。CPU密集型的计算python跟c有数量级的差距。
@ 在超算上跑python被人嘲笑的感觉就跟买了个mbp retina装了个windows XP一样,还是电脑城装机版的。PS,simulation领域
& & 07:12:13 +08:00
@ python性能差距这么大... 想使用python的初衷是看到Python上有scipy和matplotlib,以为处理跑出来的数据会方便不少
现在磁盘IO应该还没到 也是单thread在跑 主要是循环的周期太长 用Matlab一个周期要1小时多...
& & 08:38:49 +08:00
@ Sage 对于椭圆曲线非常友好。别的我不太清楚。一开始就是一些数论类的计算。
& & 13:49:04 +08:00
numpy/scipy底层都是纯C的,性能不会比matlab差。scikit-learn, genism等都是建立在numpy/scipy之上。python只是提供了一个胶水层。另外纯python部分也可以再用pypy jit一下,性能相当可观
& & 14:43:15 +08:00
不论性能,对于代码表达而言,numpy中主要类型是多维数组(可高于二维),matlab的主要类型是矩阵(二维,更加符合线性代数的表达),之前多用matlab,个人感觉matlab的表达更直接一些。
个人认为,python的优点在于其是免费的(octave
算是免费的matlab),而且与matlab的差距不大,因此越来越流行。
& & 14:47:00 +08:00
scipy足够快了,不够快的自己把瓶颈处算法改改,比换语言更有效
& & 16:37:36 +08:00
非常大,但是你可以用 numpy/scipy 获得优异的性能来解决这个问题,另外 numpy/scipy+matplotlib 的组合不输给 matlab,在很多地方上甚至超过它
& & 21:02:46 +08:00
之前模式识别的课程实验就用Sage(http://www.sagemath.org/)做的。。。
总体来说Sage不如matlab方便,比较小众,文档肯定也没matlab全。
性能还可以,如果不够的化可以再用的IntelCC重新编译numpy模块来实现CPU指令级(扩展指令集)的矩阵运算加速。
但是想锻炼自己的编程能力,可以上Python。如果只是做研究,直接matlab把。
& & 22:13:49 +08:00
MATLAB是一种解释性语言,所以在运行效率上不如C,特别是在有循环的地方。
因为我曾经用matlab做过多重循环的算法,确实很慢。
于是,我看了这篇文章:http://web.cecs.pdx.edu/~gerry/MATLAB/programming/performance.html
主要是从三方面入手:
- Using vector operations instead of loops
- Pre-allocating memory for vectors and matrices
- Correct code is most important
后来,我将原本一段耗时约500秒运行的matlab程序,用C编译后再运行,结果变快了10秒。
下面是我本科时“小打小闹”的一篇相关文章:
以上仅供参考,不知道是否有用...
& & 23:50:13 +08:00
@ 是的,使用MatLab仍旧偏向循环处理每一条数据,那就好比在数据库中放弃了sql语句而使用cursor来计算数据。建议是在更粗粒度上进行处理。
& & 23:51:14 +08:00
@ 并且,MatLab的内置矩阵操作和运算是极为优化的,手写代码一般是没有它快的
& & 01:11:35 +08:00 via iPhone
大,很大,前段时间做图像,还有一些相关的计算,算了一下,c比python快很多很多。
而且论文的话,一般要求是c和 matlab。
& & 01:13:49 +08:00 via iPhone
矩阵的话,只是计算的话用一个单列list就够用了。numpy的变换完接下来不好做。
& & 09:14:22 +08:00
正要学习scikit-learn 有什么好的建议么?
& & 09:41:13 +08:00
我感觉numpy scipy matplotlib 的组合是强于matlab的。python性能肯定不如c,所以实在追求性能可以用c写一部分性能需求高的,然后用python调用吧。
FYI,/item?id=363096
& & 12:43:57 +08:00
Python 在这方面的应用发展,从我订阅的Enthought的Newsletter来看也在不断发展中。
& & 14:32:13 +08:00
@ 说的是正解。像矩阵运算,解线性方程,FFT 这些东西无论如何都得用 C 写(或者用现成的,比如 Intel MKL)。Python 顶多写写 top-level 准备数据的胶水代码。
& & 14:54:58 +08:00 via iPhone
@ 感觉有的时候是不可靠的,有客观比较更好
& · & 2416 人在线 & 最高记录 3541 & · &
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.7.5 · 61ms · UTC 09:21 · PVG 17:21 · LAX 02:21 · JFK 05:21? Do have faith in what you're doing.

我要回帖

更多关于 最佳性能和最大化性能 的文章

 

随机推荐