用Cython编译Python的C扩展
原文地址:http://www.keakon.NET/2009/09/17/%E7%94%A8Cython%E7%BC%96%E8%AF%91Python%E7%9A%84C%E6%89%A9%E5%B1%95
大部分的Python代码并未用到其动态性,却为此多付出了很多时间,所以出于性能考虑就会改用C扩展来加速。
然而用C写代码明显比Python麻烦多了,接口的处理也很繁琐,所以我一直没去尝试。
昨晚看到一篇《Cython三分钟入门》,让我眼前一亮:居然可以把大部分Python代码直接编译成C扩展(当然手动改写会更快,和C代码速度几乎完全相同)。而且它是完全自由的,可以使用任何许可证:public domain、BSD、GPL或all rights reserved。
不过介绍前首先得提下,我认为Python主要慢在这些地方:
变量类型在运行期动态决定,且可任意更改对象结构。这使得查找对象及其属性被延迟到运行期,而很多情况下是不会在运行期更改的,因此造成很大浪费。
一切都是对象,连整数也不例外,所以连整数加法都会构造新的对象,自然比C慢。因此涉及数值计算等大量计算的场合,使用NumPy、SciPy等C编写的库或自己编写C扩展比较好。
函数调用需要构造参数元组,开销比C大,而且也不会内联。但如果函数本身的运算时间很长,远大于函数调用的开销,那也没太多必要优化。
循环语句用for ... in xrange(...)是Python中最快的方法,但内部是用yield实现的,这种跳转代价很大,CPU很难预测。
如果认为自己的代码就慢在这几点,那么就继续往下看吧。
先是安装Cython。由于我只有Windows,所以就只介绍这个平台。
英文的说明可以看《InstallingOnWindows》,共有2步:
一、安装MinGW。现在SF已不提供完整安装版了,只能下载在线安装版。由于Cython也支持C++,所以我也勾选了g++编译器。
装好后把MinGW目录/bin加入PATH环境变量,并保证gcc --version可以正确执行。
接着去Python目录\Lib\distutils下添加一个distutils.cfg文件,内容如下:
[build]
compiler = mingw32
实际上这最后一步也可不做,但每次编译都需要加一个-c参数来指定编译器。
二、安装 Cython 。
我是直接下载exe版本的,直接运行即可。Python 2.4可能还要做些额外处理,我没有这个版本,没法测试。
接着就可以来测试了,先来写个hello world。
hw.py:
def hi():print "Hello World"
setup.py:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_extsetup(cmdclass = {'build_ext': build_ext},ext_modules = [Extension("hw", ["hw.py"])]
)
然后运行这段代码进行编译:
setup.py build_ext --inplace
这就生成了很多文件,其中hw.pyd就是生成的C扩展了。
接着测试一下:
>>> from hw import hi
>>> hi()
Hello World
然后来测试下性能:
csigma.py和pysigma.py:
def sigma(n):a = 0for i in xrange(n):a += ireturn a
测试脚本:
from timeit import Timerprint Timer('sigma(10000)','from csigma import sigma').timeit(10000)
print Timer('sigma(10000)','from pysigma import sigma').timeit(10000)
结果:
3.97598186362
5.50760753112
提升了40%,不算太快。
稍微改改csigma.py,加上变量类型声明:
def sigma(int n): # 这里也可以改成cpdef int sigma(int n),速度稍慢,看来要与Python交互的函数还是不要写返回值类型比较好;而加上inline则更慢cdef int a = 0cdef int ifor i in xrange(n): # 也可写成for i from 0 <= i < n,实际上声明i为整数后,前者会自动转换成后者a += ireturn a
这下提升就非常明显了:
0.0740379014651
5.46775861178
此外,重命名为csigma.pyx,又变快了一点点,到了0.07以内了。
接着和C比较一下,由于性能提高了很多,所以把计算参数改成一百万来测试。
先修改cygwinccompiler.py,把 gcc -mno-cygwin -O 改成 gcc -mno-cygwin -O3 (还可以改写setup.py,在Extension里加上 extra_compile_args=["-O3"] ),测试结果为6694~6709毫秒。
然后是C代码:
#include <stdio.h>
#include <time.h>int sigma(int n)
{int a = 0;int i = 0; // 循环变量也可以在for里声明,但必须加上-std=c99编译参数,而且会稍慢一点for (; i < n; ++i){a += i;}return a;
}int main()
{clock_t t = clock();int i = 0;int sum;for (; i < 10000; ++i){sum = sigma(1000000);}clock_t t2 = clock();printf("%d", t2 - t);printf("\n%d", sum);return 0;
}
加上-O3参数,成绩为6671~6718毫秒,和Cython代码的速度几乎相同。
2011年9月4日更新:Cython 0.15已经发布,cython -a指令可以显示哪些代码可以加上静态类型:
用Cython编译Python的C扩展相关推荐
- Cython编译python为so 代码加密
1. 编译出来的so比网上流传的其他方法小很多. 2. language_level 是python的主版本号,如果python版本是2.x,目前的版本Cython需要人工指定language_le ...
- python编译成c语言-cython编译Python为c语言
第一种办法: 执行命令:cython test.py 结果:会在同一目录下面生成test.c文件 执行命令: gcc -c -fPIC -I /usr/include/python2.7 test.c ...
- cython编译python_Cython编译python为so 代码加密示例
1. 编译出来的so比网上流传的其他方法小很多. 2. language_level 是python的主版本号,如果python版本是2.x,目前的版本Cython需要人工指定language_le ...
- 将python编程为c_使用Cython为Python编写更快的C扩展
在我们这个包含了 7 个 PyPI 库的系列文章中学习解决常见的 Python 问题的方法. Python 是当今使用最多的流行编程语言之一,因为:它是开源的,它有广泛的用途(例如 Web 编程.业务 ...
- python源代码程序编译后的文件扩展名是什么_Python源代码程序编译后的文件扩展名为_________。...
Python源代码程序编译后的文件扩展名为_________. 答:pyc 某合同价格条款规定如下:"每打FOB上海15欧元,总值4500欧元".则此时欧元为 答:计价货币 生态文 ...
- python程序文件的扩展名称-Python源代码程序编译后的文件扩展名为( )。_学小易找答案...
[单选题]9.药物与血浆蛋白结合后( ). [填空题]根据ISO标准,当刀具中心轨迹在程序轨迹前进方向左边时称为左刀补,用( )指令表示! [判断题]进口的农产品必须按照国家规定的农产品质量安全标准进 ...
- 写python的c扩展简介
写python的c扩展简介 2012 年 10 月 05 日 isnowfy programGo to comment python是一门非常方便的动态语言,很多你用c或者java要很多行的代码,可能 ...
- 真香!spaCy+Cython比Python快100倍.....
选自Medium 作者:Thomas Wolf 编译:机器之心(almosthuman2014) Cython 是一个工具包,可以使你在 Python 中编译 C 语言,这就是为什么 num ...
- cython python3_30倍!使用Cython加速Python代码
原标题:30倍!使用Cython加速Python代码 作者:George Seif.Thomas Wolf.Lukas Frei 编译:1+1=6 | 公众号海外部 前言 你可能经常会一次又一次地听到 ...
- python在线编译-在线编译python
广告关闭 2017年12月,云+社区对外发布,从最开始的技术博客到现在拥有多个社区产品.未来,我们一起乘风破浪,创造无限可能. 尝试通过源码自己编译 python,使用的系统是 ubuntu14.04 ...
最新文章
- ICCV 2021 Oral | 无需法向的大场景点云表面重建
- 深入了解 Java 之虚拟机内存
- dwr框架ajax验证账号,dwr-Ajax开源框架
- android listview 数据数组制作,android – 从对象的数组列表中填充listview
- 【第6章 循环】while语句
- hashmap 允许key重复吗_HashTable和HashMap的区别详解
- 经典OA办公协同管理-原型UI设计-制作
- 群晖消息通知 推送服务器,群晖resync服务器
- Clean-Code: 有意义的名字
- ibm system x服务器重装系统,IBM X346服务器重装系统_xSeries 346阵列配置
- 计算机电源24针,ATX电源20针和24针接口定义
- python 列表推导 为什么快_Python中简单的列表推导式,却能解决复杂的问题,你学会了吗?...
- Andriod Studio虚拟机启动失败解决方案
- 微信小程序摄像头监控_微信小程序读取摄像头 微信调用摄像头
- nvidia-docker的安装
- 为什么我们要坚持写博客?
- win10打开模拟器蓝屏
- SQL数据库修复例子
- AD620仪表放大器介绍
- 2015-07-20-struts-struts2简介