原文地址: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扩展相关推荐

  1. Cython编译python为so 代码加密

    1. 编译出来的so比网上流传的其他方法小很多. 2. language_level  是python的主版本号,如果python版本是2.x,目前的版本Cython需要人工指定language_le ...

  2. python编译成c语言-cython编译Python为c语言

    第一种办法: 执行命令:cython test.py 结果:会在同一目录下面生成test.c文件 执行命令: gcc -c -fPIC -I /usr/include/python2.7 test.c ...

  3. cython编译python_Cython编译python为so 代码加密示例

    1. 编译出来的so比网上流传的其他方法小很多. 2. language_level  是python的主版本号,如果python版本是2.x,目前的版本Cython需要人工指定language_le ...

  4. 将python编程为c_使用Cython为Python编写更快的C扩展

    在我们这个包含了 7 个 PyPI 库的系列文章中学习解决常见的 Python 问题的方法. Python 是当今使用最多的流行编程语言之一,因为:它是开源的,它有广泛的用途(例如 Web 编程.业务 ...

  5. python源代码程序编译后的文件扩展名是什么_Python源代码程序编译后的文件扩展名为_________。...

    Python源代码程序编译后的文件扩展名为_________. 答:pyc 某合同价格条款规定如下:"每打FOB上海15欧元,总值4500欧元".则此时欧元为 答:计价货币 生态文 ...

  6. python程序文件的扩展名称-Python源代码程序编译后的文件扩展名为( )。_学小易找答案...

    [单选题]9.药物与血浆蛋白结合后( ). [填空题]根据ISO标准,当刀具中心轨迹在程序轨迹前进方向左边时称为左刀补,用( )指令表示! [判断题]进口的农产品必须按照国家规定的农产品质量安全标准进 ...

  7. 写python的c扩展简介

    写python的c扩展简介 2012 年 10 月 05 日 isnowfy programGo to comment python是一门非常方便的动态语言,很多你用c或者java要很多行的代码,可能 ...

  8. 真香!spaCy+Cython比Python快100倍.....

    选自Medium      作者:Thomas Wolf 编译:机器之心(almosthuman2014) Cython 是一个工具包,可以使你在 Python 中编译 C 语言,这就是为什么 num ...

  9. cython python3_30倍!使用Cython加速Python代码

    原标题:30倍!使用Cython加速Python代码 作者:George Seif.Thomas Wolf.Lukas Frei 编译:1+1=6 | 公众号海外部 前言 你可能经常会一次又一次地听到 ...

  10. python在线编译-在线编译python

    广告关闭 2017年12月,云+社区对外发布,从最开始的技术博客到现在拥有多个社区产品.未来,我们一起乘风破浪,创造无限可能. 尝试通过源码自己编译 python,使用的系统是 ubuntu14.04 ...

最新文章

  1. ICCV 2021 Oral | 无需法向的大场景点云表面重建
  2. 深入了解 Java 之虚拟机内存
  3. dwr框架ajax验证账号,dwr-Ajax开源框架
  4. android listview 数据数组制作,android – 从对象的数组列表中填充listview
  5. 【第6章 循环】while语句
  6. hashmap 允许key重复吗_HashTable和HashMap的区别详解
  7. 经典OA办公协同管理-原型UI设计-制作
  8. 群晖消息通知 推送服务器,群晖resync服务器
  9. Clean-Code: 有意义的名字
  10. ibm system x服务器重装系统,IBM X346服务器重装系统_xSeries 346阵列配置
  11. 计算机电源24针,ATX电源20针和24针接口定义
  12. python 列表推导 为什么快_Python中简单的列表推导式,却能解决复杂的问题,你学会了吗?...
  13. Andriod Studio虚拟机启动失败解决方案
  14. 微信小程序摄像头监控_微信小程序读取摄像头 微信调用摄像头
  15. nvidia-docker的安装
  16. 为什么我们要坚持写博客?
  17. win10打开模拟器蓝屏
  18. SQL数据库修复例子
  19. AD620仪表放大器介绍
  20. 2015-07-20-struts-struts2简介

热门文章

  1. 使用Zephir来快速编写高性能PHP二进制拓展
  2. 041——VUE中组件之pros数据的多种验证机制实例详解
  3. 修改设置Tomcat内存
  4. Ubuntu Desktop 变为 Ubuntu Server 服务器版的方法
  5. 功夫熊猫2观后感,无剧透,放心进
  6. 08Oracle Database 完整性约束
  7. selenium窗口截图操作
  8. Fiddler工具使用介绍三
  9. Adobe Flash runtimes路线图
  10. 由摄像机的内参K计算视景体——glFrustum的参数推导