用Cython加速Python程序以及包装C程序简单测试
用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程序简单测试的更多相关文章
- 用Cython加速Python代码
安装Cython pip install Cython 如何使用 要在我们的笔记本中使用Cython,我们将使用IPython magic命令.Magic命令以百分号开始,并提供一些额外的功能,这些功 ...
- 使用numba加速python程序
前面说过使用Cython来加速python程序的运行速度,但是相对来说程序改动较大,这次就说一种简单的方式来加速python计算速度的方法,就是使用numba库来进行,numba库可以使用JIT技术即 ...
- 利用Cython对python代码进行加密
利用Cython对python代码进行加密 Cython是属于PYTHON的超集,他首先会将PYTHON代码转化成C语言代码,然后通过c编译器生成可执行文件.优势:资源丰富,适合快速开发.翻译成C后速 ...
- 完成一段简单的Python程序,用于实现一个简单的加减乘除计算器功能
#!/bin/usr/env python#coding=utf-8'''完成一段简单的Python程序,用于实现一个简单的加减乘除计算器功能'''try: a=int(raw_input(" ...
- Spring MVC 程序首页的设置 - 一号门-程序员的工作,程序员的生活(java,python,delphi实战)
body { font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI ...
- python爬虫程序打包为exe程序并在控制台下运行
上一篇文章实现了爬取任意两个用户共同想读的图书的python程序.现在此程序打包为exe程序. 使用pyinstaller实现此功能.在pyinstaller官网下载http://www.pyinst ...
- 用python + hadoop streaming 编写分布式程序(一) -- 原理介绍,样例程序与本地调试
相关随笔: Hadoop-1.0.4集群搭建笔记 用python + hadoop streaming 编写分布式程序(二) -- 在集群上运行与监控 用python + hadoop streami ...
- 用python + hadoop streaming 编写分布式程序(二) -- 在集群上运行与监控
写在前面 相关随笔: Hadoop-1.0.4集群搭建笔记 用python + hadoop streaming 编写分布式程序(一) -- 原理介绍,样例程序与本地调试 用python + hado ...
- 用python + hadoop streaming 编写分布式程序(三) -- 自定义功能
又是期末又是实训TA的事耽搁了好久……先把写好的放上博客吧 相关随笔: Hadoop-1.0.4集群搭建笔记 用python + hadoop streaming 编写分布式程序(一) -- 原理介绍 ...
随机推荐
- asp.net textbox控件基础
asp.net有两种控件,一种是html控件,一种是asp控件,在说textbox控件之前,先看看按钮的两个命令oncommand和onclick.每次点击按钮后,都会提交命令,但是程序会首先执行Pa ...
- VM 443端口冲突解决办法
netstat -aon|findstr "443" 找到占用443的进程号: tasklist|findstr "2016" 根据进程号2016找到占用443 ...
- 解压tomcat后一闪而过的问题
解压tomcat压缩包后,直接点击startup会出现一闪而过. 免安装的tomcat双击startup.bat后,启动窗口一闪而过,而且tomcat服务未启动. 原因是:在启动tomcat是,需要读 ...
- Python你必须知道的十个库
Python是优雅的,使用这些库可以使你的代码更简洁,并保持持久性.欢迎各位补充,并提出意见! Docopt.抛弃optparse和argparse吧,使用docstrings来构建优雅的,可读性强的 ...
- WIN7/8系统下程序接收不到WM_COPYDATA 消息的原因和解决
在WIN7/win8,如果发送消息的程序用户权限低于和接收消息的程序,则消 息无法传递.发送程序必须等于或者等于接收程序的权限.如发送与接收 是同一个用户,或者发送是管理员帐户,接收是是普通用户,这样 ...
- python初学笔记(三)
Unicode字符串 字符串还有一个编码问题. 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特(bit)作为一个字节 (byte),所以,一 ...
- [LeetCode]题解(python):155-Min Stack
题目来源: https://leetcode.com/problems/min-stack/ 题意分析: 实现一个小的栈,包括初始化,push,pop,top,和getMin. 题目思路: 私用是用两 ...
- [C#]Windows文件分类器小程序
我平时习惯把各种文件都下载在`下载`文件夹中,时间久了,文件多了,想要找个文件就不那么方便了.于是我就想自己写一个小程序来实现下载文件的自动整理.我想到的文件分类方式是按照文件扩展名分类:把各文件移动 ...
- Codis集群的搭建
Codis集群的搭建与使用 一.简介 Codis是一个分布式的Redis解决方案,对于上层的应用来说,连接Codis Proxy和连接原生的Redis Server没有明显的区别(不支持的命令列表 ...
- 解决:未能加载文件或程序集“Newtonsoft.Json, Version=4.5.0.0
开发环境:Microsoft Visual Studio 2013 MVC4.0 使用SignalR的过程中随着版本的升级,其它程序集也跟着升级,如Newtonsoft.Json,一般编译的时候,如果 ...