Cython入门:将python代码转为cython
前言
本节不具体讲解cython的原理和细节,提供一个最简单的例子,将一个python代码转化为一个cython代码,同时由于本人对cython刚入门,只会一个简单的操作,即在cython中声明变量的类型。实验证明,就这样简单添加变量类型,代码运行速度提升了将近4倍
cython对于代码中许多循环的情况很有帮助!
python代码
这里给的是CVPPP官方提供的evaluate代码(evaluate.py)
为了节省空间,这里删除了注释和一些无关紧要的判断语句
import numpy as np
def DiffFGLabels(inLabel,gtLabel):maxInLabel = np.int(np.max(inLabel))minInLabel = np.int(np.min(inLabel))maxGtLabel = np.int(np.max(gtLabel))minGtLabel = np.int(np.min(gtLabel))return (maxInLabel-minInLabel) - (maxGtLabel-minGtLabel) def BestDice(inLabel,gtLabel):score = 0maxInLabel = np.max(inLabel) minInLabel = np.min(inLabel) maxGtLabel = np.max(gtLabel) minGtLabel = np.min(gtLabel) if(maxInLabel==minInLabel):return scorefor i in range(minInLabel+1,maxInLabel+1):sMax = 0; for j in range(minGtLabel+1,maxGtLabel+1): s = Dice(inLabel, gtLabel, i, j) if(sMax < s):sMax = sscore = score + sMax; score = score/(maxInLabel-minInLabel)return scoredef FGBGDice(inLabel,gtLabel):minInLabel = np.min(inLabel) minGtLabel = np.min(gtLabel) one = np.ones(inLabel.shape) inFgLabel = (inLabel != minInLabel*one)*onegtFgLabel = (gtLabel != minGtLabel*one)*onereturn Dice(inFgLabel,gtFgLabel,1,1)def Dice(inLabel, gtLabel, i, j):one = np.ones(inLabel.shape)inMask = (inLabel==i*one) gtMask = (gtLabel==j*one) inSize = np.sum(inMask*one) gtSize = np.sum(gtMask*one) overlap= np.sum(inMask*gtMask*one) if ((inSize + gtSize)>1e-8):out = 2*overlap/(inSize + gtSize) else:out = 0return outdef AbsDiffFGLabels(inLabel,gtLabel):return np.abs( DiffFGLabels(inLabel,gtLabel) )def SymmetricBestDice(inLabel,gtLabel):bd1 = BestDice(inLabel,gtLabel)bd2 = BestDice(gtLabel,inLabel)if bd1 < bd2:return bd1else:return bd2
Cython代码
创建一个evaluate.pyx文件(注意:后缀得是pyx!!!)
from __future__ import division
from libcpp cimport bool as bool_t
import numpy as np
cimport numpy as np
cimport cythonctypedef bint TYPE_BOOL
ctypedef unsigned long long TYPE_U_INT64
ctypedef unsigned int TYPE_U_INT32
ctypedef unsigned short TYPE_U_INT16
ctypedef unsigned char TYPE_U_INT8
ctypedef long long TYPE_INT64
ctypedef int TYPE_INT32
ctypedef short TYPE_INT16
ctypedef signed char TYPE_INT8
ctypedef float TYPE_FLOAT
ctypedef double TYPE_DOUBLE@cython.boundscheck(False) # turn off bounds-checking for entire function
@cython.wraparound(False) # turn off negative index wrapping for entire function
def DiffFGLabels(np.ndarray[TYPE_U_INT16, ndim=2] inLabel, np.ndarray[TYPE_U_INT16, ndim=2] gtLabel):cdef int maxInLabel = np.int(np.max(inLabel)) cdef int minInLabel = np.int(np.min(inLabel)) cdef int maxGtLabel = np.int(np.max(gtLabel)) cdef int minGtLabel = np.int(np.min(gtLabel)) cdef double out = (maxInLabel-minInLabel) - (maxGtLabel-minGtLabel)return out@cython.boundscheck(False)
@cython.wraparound(False)
def BestDice(np.ndarray[TYPE_U_INT16, ndim=2] inLabel, np.ndarray[TYPE_U_INT16, ndim=2] gtLabel):cdef int i, jcdef double sMax = 0.0cdef double s = 0.0cdef double score = 0.0 cdef int maxInLabel = np.max(inLabel) cdef int minInLabel = np.min(inLabel) cdef int maxGtLabel = np.max(gtLabel) cdef int minGtLabel = np.min(gtLabel) if(maxInLabel == minInLabel): return scorefor i in range(minInLabel+1, maxInLabel+1):sMax = 0;for j in range(minGtLabel+1, maxGtLabel+1):s = Dice(inLabel, gtLabel, i, j) if(sMax < s):sMax = sscore = score + sMax;score = score / (maxInLabel-minInLabel)return score@cython.boundscheck(False)
@cython.wraparound(False)
def FGBGDice(np.ndarray[TYPE_U_INT16, ndim=2] inLabel, np.ndarray[TYPE_U_INT16, ndim=2] gtLabel):cdef int minInLabel = np.min(inLabel) cdef int minGtLabel = np.min(gtLabel) cdef np.ndarray[TYPE_U_INT16, ndim=2] one = np.ones_like(inLabel)cdef np.ndarray[TYPE_U_INT16, ndim=2] inFgLabel = (inLabel != minInLabel*one)*onecdef np.ndarray[TYPE_U_INT16, ndim=2] gtFgLabel = (gtLabel != minGtLabel*one)*onecdef double out = Dice(inFgLabel,gtFgLabel,1,1) return out@cython.boundscheck(False)
@cython.wraparound(False)
def Dice(np.ndarray[TYPE_U_INT16, ndim=2] inLabel, np.ndarray[TYPE_U_INT16, ndim=2] gtLabel, int i, int j):cdef double out = 0.0cdef np.ndarray[TYPE_U_INT16, ndim=2] one = np.ones_like(inLabel)cdef int inSize = np.sum((inLabel==i*one)*one) cdef int gtSize = np.sum((gtLabel==j*one)*one) cdef int overlap= np.sum((inLabel==i*one)*(gtLabel==j*one)*one) if ((inSize + gtSize)>1e-8):out = 2*overlap/(inSize + gtSize) else:out = 0return out@cython.boundscheck(False)
@cython.wraparound(False)
def AbsDiffFGLabels(np.ndarray[TYPE_U_INT16, ndim=2] inLabel, np.ndarray[TYPE_U_INT16, ndim=2] gtLabel):cdef double out = np.abs(DiffFGLabels(inLabel, gtLabel))return out@cython.boundscheck(False)
@cython.wraparound(False)
def SymmetricBestDice(np.ndarray[TYPE_U_INT16, ndim=2] inLabel, np.ndarray[TYPE_U_INT16, ndim=2] gtLabel):cdef double bd1 = BestDice(inLabel,gtLabel)cdef double bd2 = BestDice(gtLabel,inLabel)if bd1 < bd2:return bd1else:return bd2
编译
写好pyx文件后,需要再写一个setup.py文件,里面的内容也很简单(注意修改相应的pyx文件名!!!):
import distutils.core
import Cython.Build
import numpy as np
distutils.core.setup(ext_modules = Cython.Build.cythonize("evaluate.pyx"),include_dirs = [np.get_include()])
编译:
python setup.py build_ext --inplace
编译成功后,就可以正常的 import 里面的函数了
解释
通过对比两个代码,我们可以看出一些规律也可以总结出一些规律
- 在导入包的时候,有一句最重要的是:cimport numpy as np,表明使用的是cython接口的numpy。(当然也有import numpy as np,编译器会根据情况使用numpy还是c-numpy);还有一句是:from libcpp cimport bool as bool_t,这是为了使用C语言中的bool类型(这个例子里面没有用到bool类型,可以不用管)
- 为数据类型起一个新名字:ctypedef。这个不是必须,但这里为了可读性,我列举了一些numpy中常用的数据类型对应的C语言中的数据类型
numpy | C |
---|---|
np.uint8 | unsigned char |
np.uint16 | unsigned short |
np.uint32 | unsigned int |
np.uint64 | unsigned long long |
np.int8 | signed char |
np.int16 | short |
np.int32 | int |
np.int64 | long long |
np.float32 | double |
- 每个函数前面都有:@cython.boundscheck(False) 和 @cython.wraparound(False),这是为了加速而关闭边界检查,这样做就需要提前保证代码的准确性,建议在python下验证代码的准确性
- 每个函数的输入变量都定义了数据类型,比如这里全是:np.ndarray[TYPE_U_INT16, ndim=2],这表明输入的一个二维的uint16的numpy数组,如果输入类型不是这样,那就会报错
- cdef int/double:定义整型/双精度浮点型变量。在使用每个变量须先对它进行定义,如果没有编译器就会花时间来判断,就会耗时
Cython入门:将python代码转为cython相关推荐
- python游戏中调整箭头下落速度_入门 | 三行Python代码,让数据预处理速度提高2到6倍...
原标题:入门 | 三行Python代码,让数据预处理速度提高2到6倍 选自TowardsDataScience 作者:George Seif,机器之心编译 在 Python 中,我们可以找到原生的并行 ...
- python代码使用cython进行加密
python代码加密 前言 加密的多种方式 Cython加密 步骤 注意 部署 前言 加密的多种方式 发布编译过的pyc文件 缺点:很容易被反编译 PyInstaller 是一个用来将 Python ...
- jsonarray转化list对象_第8篇:Cython的面向对象--Python类 vs Cython扩展类
在Python中,一切都是对象. 具体来说是什么意思? 在最基本的层面上,一个对象具有三样东西 标识(id):对象的标识将其与其他对象区分开来,并由id内置函数提供 属性值(value):对象的值就是 ...
- 「Python入门」Python代码规范(风格)
活动地址:CSDN21天学习挑战赛 文章目录 前言 一.编码规范 二.分号 三.行的最大长度 四. 缩进规则 五.Python注释 5.1 行注释 5.2 块注释 5.3 文档注释 六. Py ...
- 分形几何python代码_Python, Cython绘制美妙绝伦的Mandelbrot集, 曼德博集分形图案
上世纪60-70年代,美籍数学家曼德博 - Benoit B. Mandelbrot几乎单枪匹马的创立了一个新的数学分支,即分形几何学 - fractal geometry.这个新的数学分支有助于人类 ...
- cython python3_30倍!使用Cython加速Python代码
原标题:30倍!使用Cython加速Python代码 作者:George Seif.Thomas Wolf.Lukas Frei 编译:1+1=6 | 公众号海外部 前言 你可能经常会一次又一次地听到 ...
- python 大项目使用cython_提升6.75倍!利用Cython为Python代码加速
全文共2012字,预计学习时长4分钟 图片来源:Unsplash 如果你曾经用Python编写过代码,可能会发现等待某些代码块执行的时间比预期要长.尽管可以通过一些方法提高其代码效率,但它的反应速度仍 ...
- 什么是Cython?让Python有C语言的速度
Python的一个超集,可以编译为C,Cython结合了Python的易用性和原生代码的速度. Python作为最方便,丰富的配置和彻底有用的编程语言之一而享有盛誉. 但执行速度?没那么快. 让我们开 ...
- python append函数_让你python代码更快的3个小技巧!速度提高了一倍还多
大家好!今天呢,我们来聊一聊如何加速你的 python 代码. Python 语言的优点可以列举出许多,语法简单易懂.模块丰富.应用广泛等等.但是世界上没有有完美的东西,python 一个明显缺点就是 ...
最新文章
- KMP-next数组
- On-Heap与Off-Heap
- 通过angular.js实现MVC的基本步骤
- 我用python是什么梗_Python中的一些梗
- iOS 界面上绘制不同字体 颜色 大小的字符串
- tomcat错误:The page you tried to access (/manager/login.do) does not exist
- RUP,XP,敏捷原理
- C++ STL 线性容器的用法
- Keras-Sequential模型(2)
- [转载] Python format()格式:中文对齐问题
- MySQL 常用基础命令
- oracle shared_pool_size 0,Oracle 参数shared_pool_size
- VHDL实现交通灯程序
- 武汉大学计算机学院推免率,武汉大学保研率
- 【编译原理】 CS143 斯坦福大学公开课 第一周:简介
- 屏幕录像软件Community Clips Recorder简介及其使用技巧(郝宪玮)
- 关于PostgreSQL软件安装后出现解决the application server could not be contect ed错误的方法
- 毕业实习感想—软件测试
- Odoo隐藏应用模块
- flink catalog 及dialect、数据转存分析