用Cython加速Python程序

我没有拼错,就是Cython,C+Python=Cython!

我们来看看Cython的威力,先运行下边的程序:

import time

def fib(n):
if n==0:
return 0
if n==1:
return 1
return fib(n-1)+fib(n-2)
t=time.time()
print(fib(40))
print(time.time()-t) $ python fib.py
102334155
59.367255449295044

在我的渣渣笔记本上,用时59.3秒,差不多一分钟。当然,在你那可能比我快一点,这也很正常。

好了,我们再试试Cython:

$ cython fib.py --embed
$ gcc -O3 fib.c -I /usr/include/python3.5m/ -lpython3.5m
$ ./a.out
102334155
14.487313747406006

嗯,快了那么一点点,4倍左右;我解释一下前边的几句代码:

首先,用cython命令把python生成c文件,也就是cython fib.py会生成一个fib.c的文件

--embed参数就是自动生成一个main函数,以便让gcc生成可执行程序。

接下来就是用gcc把fib.c编译成了个a.out程序,运行之,结果快了4倍(从60秒减少到15秒以内)。

当然,这只是小试牛刀,区区4倍而已,这也太少了!

接下来我吧这个文件复制成fib.pyx,并修改了一句代码:

import time

cdef int fib(int n):
if n==0:
return 0
if n==1:
return 1
return fib(n-1)+fib(n-2)
t=time.time()
print(fib(40))
print(time.time()-t)

我只改了1句,就是把 def fib(n):改成了 cdef int fib(int n):,也就是加了一个类型,下边让我们见证奇迹:

$ cython fib.pyx --embed
$ gcc -O3 fib.c -I /usr/include/python3.5m/ -lpython3.5m
$ ./a.out
102334155
0.45729994773864746

没有看错,现在只需要0.45秒!性能提升了132倍。

这个0.45秒算是什么样的速度呢?下边,我照猫画虎,写了基本相同的一段C程序:

#include "stdio.h"

#include "time.h"

static int fib(int n){
if(n==0)
return 0;
if(n==1)
return 1;
return fib(n-1)+fib(n-2);
}
int main(){
clock_t t=clock();
printf("%d\n",fib(40));
printf("%f sec\n",(clock()-t)/1000.0/1000.0);
}

这个跟python写的基本一模一样,只是换成了C语法,然后:

$ gcc -O3 fib.c
$ ./a.out
102334155
0.452981 sec

天,只比刚才Cython的程序慢了0.005秒(我觉得这已经是误差了)

是不是感觉Cython碉堡了?(基本用Python的语法,实现了C的速度。

其实,这才刚刚开始。毕竟虽然Python代码写起来比C溜好多,但以前的C代码怎么办?并且,一些C实现的算法

用Cython改写也不是特别方便,能不能直接拿来就用呢?当然能,并且也可以很6。

比如上边的那个fib函数,我已经用C写完了,怎么整合到Python里边呢?

首先,我先把C里边的main函数去掉,改成下边的样子:

#include "stdio.h"
#include "time.h" static int fib(int n){
if(n==0)
return 0;
if(n==1)
return 1;
return fib(n-1)+fib(n-2);
}

其实这时,我们已经可以用gcc编译成一个链接库,用ctypes调用了,然而在Cython看来,

这太(调)不(用)清(麻)真(烦),我们只需要2句代码:

cdef extern from "fib.c":
int fib(int) def fibf(n):
return fib(n)

虽然是4行,其实也就是2句无疑:)

第一句我先把fib函数从C文件里边导入,然后又定义了一个fibf的函数,把导进来的函数又调用了一下。

cdef的作用,就是把外部函数导出为cython能调用的函数,def的作用就是定义python能调用的函数了。

把这个文件保存成fibf.pyx,然后:

cython fibf.pyx
gcc fibf.c -shared -fPIC -I /usr/include/python3.5m -lpython3.5m -o fibf.so -O3

把这个文件编译成了一个fibf.so文件

然后写了下边的python代码测试:

$cat test.py
import time
import fibf
t=time.time()
print(fibf.fibf(40))
print(time.time()-t) python test.py
102334155
0.47469592094421387

也就是说,2句代码,就把一个C语言写的代码。包装成了一个python能直接import的库。是不是方便极了……

反正个人觉得比ctypes方便。

用Cython加速Python程序以及包装C程序简单测试的更多相关文章

  1. 用Cython加速Python代码

    安装Cython pip install Cython 如何使用 要在我们的笔记本中使用Cython,我们将使用IPython magic命令.Magic命令以百分号开始,并提供一些额外的功能,这些功 ...

  2. 使用numba加速python程序

    前面说过使用Cython来加速python程序的运行速度,但是相对来说程序改动较大,这次就说一种简单的方式来加速python计算速度的方法,就是使用numba库来进行,numba库可以使用JIT技术即 ...

  3. 利用Cython对python代码进行加密

    利用Cython对python代码进行加密 Cython是属于PYTHON的超集,他首先会将PYTHON代码转化成C语言代码,然后通过c编译器生成可执行文件.优势:资源丰富,适合快速开发.翻译成C后速 ...

  4. 完成一段简单的Python程序,用于实现一个简单的加减乘除计算器功能

    #!/bin/usr/env python#coding=utf-8'''完成一段简单的Python程序,用于实现一个简单的加减乘除计算器功能'''try: a=int(raw_input(" ...

  5. Spring MVC 程序首页的设置 - 一号门-程序员的工作,程序员的生活(java,python,delphi实战)

    body { font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI ...

  6. python爬虫程序打包为exe程序并在控制台下运行

    上一篇文章实现了爬取任意两个用户共同想读的图书的python程序.现在此程序打包为exe程序. 使用pyinstaller实现此功能.在pyinstaller官网下载http://www.pyinst ...

  7. 用python + hadoop streaming 编写分布式程序(一) -- 原理介绍,样例程序与本地调试

    相关随笔: Hadoop-1.0.4集群搭建笔记 用python + hadoop streaming 编写分布式程序(二) -- 在集群上运行与监控 用python + hadoop streami ...

  8. 用python + hadoop streaming 编写分布式程序(二) -- 在集群上运行与监控

    写在前面 相关随笔: Hadoop-1.0.4集群搭建笔记 用python + hadoop streaming 编写分布式程序(一) -- 原理介绍,样例程序与本地调试 用python + hado ...

  9. 用python + hadoop streaming 编写分布式程序(三) -- 自定义功能

    又是期末又是实训TA的事耽搁了好久……先把写好的放上博客吧 相关随笔: Hadoop-1.0.4集群搭建笔记 用python + hadoop streaming 编写分布式程序(一) -- 原理介绍 ...

随机推荐

  1. Java 获取 文件md5校验码

    讯雷下载的核心思想是校验文件的md5值,两个文件若md5相同则为同一文件. 当得到用户下载某个文件的请求后它根据数据库中保留的文件md5比对出拥有此文件的url, 将用户请求挂接到此url上并仿造一个 ...

  2. Windows Server 2008防火墙问题及Sql Server2005用户登录问题

    一.Windows Server 2008防火墙问题 1.  问题: 1.在 Windows 安全中心中单击“立即打开”以打开 Windows 防火墙时,会收到以下错误消息:安全中心无法打开 Wind ...

  3. 说出x的结果,并解释为什么?

    var x = 1; if(function f(){}){ x += typeof f; } x; //x的结果是? x=1undefined 首先是 if表达式的问题 if括号里,不一定非要用== ...

  4. mud目录命令说明

      目錄結構 以下列出的是 ES2 mudlib 根目錄下標準的子目錄結構,以及簡短的說明. /adm 儲存由系統管理者所管理的程式與資料檔. /std 儲存標準物件的程式碼. /obj 儲存通用物件 ...

  5. Some good questions

    (一)#include <stdio.h>#include <stdlib.h>void getmemory(char *p){ p=(char *) malloc(100); ...

  6. PHP之MVC微型框架简单搭建

    好长时间没有写博客了,这段时间过得紧张的不行,以致于都没有抽出时间来好好的总结一下自己这段时间的生活和学习. 其实今天不想写什么技术博客,就想简单总结一下这段时间的生活.10月8号从家里回来以后决定自 ...

  7. Javascript面向对象之创建对象

    面向对象的语言具有一个共同的标志,那就是具有“类”的概念,但是在javascript中没有类的概念,在js中将对象定义为“无序属性的集合,其属性可以包含基本值,对象或者函数”,即其将对象看作是一组名值 ...

  8. flex4 日期类型字符串转日期类型(string转Date)(转)

    mysql数据库中存储的日期类型通过PHP返回到flex端为字符串类型,这样在flex中进行处理时就必须要将字符串转化为Date类型.如果仅仅是 "年/月/日" 的组合,而没有涉及 ...

  9. 二道shell面试题

    1.按照给出的运行结果,编写一个名为xunhuan 的shell过程(用循环语句). 0 10 210 3210 43210 543210 6543210 76543210 876543210 2.编 ...

  10. Unix/Linux环境C编程入门教程(7) OPENBSDCCPP开发环境搭建

    1. 年发起了OpenBSD 专案,希望创造一个注重安全的操作系统. 2.创建一个虚拟机. 3.选择默认的workstation10.0 4.我们选择稍后安装操作系统. 5.我们选择FreeBSD64 ...