『Python CoolBook』Cython_高效数组操作
数组运算加速是至关科学计算重要的领域,本节我们以一个简单函数为例,使用C语言为python数组加速。
一、Cython
本函数为一维数组修剪最大最小值
version1
@cython.boundscheck(False)
@cython.wraparound(False)
cpdef clip(double[:] a, double min, double max, double[:] out):'''Clip the values in a to be between min and max. Result in out'''if min > max:raise ValueError("min must be <= max")if a.shape[0] != out.shape[0]:raise ValueError("input and output arrays must be the same size")for i in range(a.shape[0]):if a[i] < min:out[i] = minelif a[i] > max:out[i] = maxelse:out[i] = a[i]
利用Cython类型的内存视图,极大的简化了数组的操作。
cpdef clip()
声明了clip()
同时为C级别函数以及Python级别函数。 在Cython中,这个是很重要的,因为它表示此函数调用要比其他Cython函数更加高效 (比如你想在另外一个不同的Cython函数中调用clip())。- 类型参数
double[:] a
和double[:] out
声明这些参数为一维的双精度数组。 作为输入,它们会访问任何实现了内存视图接口的数组对象,这个在PEP 3118有详细定义。 包括了NumPy中的数组和内置的array库。 clip()
定义之前的两个装饰器可以优化下性能:@cython.boundscheck(False)
省去了所有的数组越界检查, 当你知道下标访问不会越界的时候可以使用它@cython.wraparound(False)
消除了相对数组尾部的负数下标的处理(类似Python列表)
version2_条件表达式
任何时候处理数组时,研究并改善底层算法同样可以极大的提示性能
@cython.boundscheck(False)
@cython.wraparound(False)
cpdef clip(double[:] a, double min, double max, double[:] out):if min > max:raise ValueError("min must be <= max")if a.shape[0] != out.shape[0]:raise ValueError("input and output arrays must be the same size")for i in range(a.shape[0]):out[i] = (a[i] if a[i] < max else max) if a[i] > min else min
version3_释放GIL
释放GIL,这样多个线程能并行运行,要这样做的话,需要修改代码,使用 with nogil:
@cython.boundscheck(False)
@cython.wraparound(False)
cpdef clip(double[:] a, double min, double max, double[:] out):if min > max:raise ValueError("min must be <= max")if a.shape[0] != out.shape[0]:raise ValueError("input and output arrays must be the same size")with nogil:for i in range(a.shape[0]):out[i] = (a[i] if a[i] < max else max) if a[i] > min else min
编写setup.py
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_extext_modules = [Extension('sample',['sample.pyx'])
]setup(name = 'Sample app',cmdclass = {'build_ext': build_ext},ext_modules = ext_modules
)
使用 python3 setup.py build_ext --inplace
来构建它
效率测试示意如下,
>>> import sample >>> import numpy >>> b = numpy.random.uniform(-10,10,size=1000000) >>> c = numpy.zeros_like(b)>>> import timeit>>> timeit.timeit('numpy.clip(b,-5,5,c)','from __main__ import b,c,numpy',number=1000)>>> timeit.timeit('sample.clip(b,-5,5,c)','from __main__ import b,c,sample', ... number=1000)
其中使用numpy自己的clip对比试验,
2.6287411409430206 # numpy
2.8034782900940627 # v1
2.7247575907967985 # v2
2.6071253868285567 # v3
版本三近似于numpy的实现效果,其他版本差一些(每次试验结果都会略有差异,这里只是粗略的比较一下)。
二维数组处理版本参考:
@cython.boundscheck(False)
@cython.wraparound(False)
cpdef clip2d(double[:,:] a, double min, double max, double[:,:] out):if min > max:raise ValueError("min must be <= max")for n in range(a.ndim):if a.shape[n] != out.shape[n]:raise TypeError("a and out have different shapes")for i in range(a.shape[0]):for j in range(a.shape[1]):if a[i,j] < min:out[i,j] = minelif a[i,j] > max:out[i,j] = maxelse:out[i,j] = a[i,j]
二、自己写接口
点击进入项目
sample.c中添加
/* n:longth of array */
void clip(double *a, int n, double min, double max, double *out) {double x;for (; n >= 0; n--, a++, out++) {x = *a;*out = x > max ? max : (x < min ? min : x);}
}
pysample.c中添加
// void clip(double *a, int n, double min, double max, double *out);
static PyObject *py_clip(PyObject *self, PyObject *args){PyObject *a, *out;int min, max;if(!PyArg_ParseTuple(args, "OiiO", &a, &min, &max, &out)){ //py数组对象暂记return NULL;}// printf("%i, %i\n", min, max);Py_buffer view_a, view_out; //py数组对象接收对象if (PyObject_GetBuffer(a, &view_a,PyBUF_ANY_CONTIGUOUS | PyBUF_FORMAT) == -1) {return NULL;}if (PyObject_GetBuffer(out, &view_out,PyBUF_ANY_CONTIGUOUS | PyBUF_FORMAT) == -1) {return NULL;}clip(view_a.buf, view_a.shape[0], min, max, view_out.buf);PyBuffer_Release(&view_a);PyBuffer_Release(&view_out);return Py_BuildValue("");
}
函数登记处添加
{"clip", py_clip, METH_VARARGS, "clip array"},
则可,实际测试发现,手动接口效率也很高,和numpy同一水平。
转载于:https://www.cnblogs.com/hellcat/p/9130241.html
『Python CoolBook』Cython_高效数组操作相关推荐
- 『python爬虫』26. selenium与超级鹰处理复杂验证码的处理(保姆级图文)
目录 1. 图片选择类验证码 2. 滑块验证码 3. 滑块出错,不加载 总结 欢迎关注 『python爬虫』 专栏,持续更新中 欢迎关注 『python爬虫』 专栏,持续更新中 1. 图片选择类验证码 ...
- 拼写单词 给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars。 假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符
力扣1160. 拼写单词 给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars. 假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字 ...
- 『python爬虫』16. 多线程与多进程(保姆级图文)
目录 多线程 1. 什么是多线程? 2. 串行模式 3. 多线程 3.1 多线程方法写法 3.2 多线程方法带参数 3.3 多线程类写法 多进程 1. 什么是多进程 欢迎关注 『python爬虫』 专 ...
- [转载] python+opencv图像处理:numpy数组操作
参考链接: Python中的numpy.pv 图片以矩阵的形式存在电脑里,需要用到数组操作来完成对图像的处理 常用的有两个API: zeros和ones 1 np.ones(size) 可以创建任意维 ...
- python观察日志(part26)--numpy数组操作
学习笔记,仅供参考,有错必究 数组操作 # 垂直方向和并数组 arr1 = np.array([[1, 2, 3], [0, 0, 1]]) arr2 = np.array([[4, 5, 6], [ ...
- 『python思考』关于列表的浅复制和深复制的理解
>>> mylist1 = [1, 2, 3, 4] >>> myl = mylist1 >>> myl [1, 2, 3, 4] >> ...
- python数据分析做什么作业好_知识星球 | 说说我为什么要做『python数据分析』社群...
过去一段时间,很多人会问我: "现在的工作没有前途,该如何转行?" "我知道数据时代已经来了,我该如何学习,不让自己落伍?" "数据分析适用于生活和工 ...
- 『Python × C++』函数传参机制学习以及对比
一.Python函数传参 在python中,函数传参实际上传入的是变量的别名,由于python内在的变量机制(名称和变量值相互独立),只要传入的变量不可变(tuple中的元素也要是不可变的才行),那么 ...
- 『Python基础』第三节:变量和基础数据类型
一. 变量 1. 变量是什么? 变量,是指把程序运行的中间结果临时的存在内存里,以便后续的代码调用,其值可以修改. 在python中,当变量被使用时,在内存里将产生两个动作,一是开辟指定地址的空间,二 ...
最新文章
- 服务端如何识别是selenium在访问以及解决方案参考二
- sudo出现sudo:must be setuid root问题的解决方法
- js data日期初始化的5种方法 [转]
- java小票_Java编程打印购物小票实现代码
- 线程魔术技巧:Java线程可以做的5件事
- WebPart的使用
- 从Slice_Header学习H.264(三.2)--相关细节之 参考图像列表
- 障碍期权定价 python_python障碍式期权定价公式
- python面向对象编程思想_面向对象编程思想及其特点
- 见山只是山 见水只是水——提升对继承的认识
- dd dt标签 显示与隐藏
- 我用 python 做了款可开淘宝店赚钱的工具
- 如何使用uni-app做一个音乐播放器
- 安卓APP开发发展趋势与前景
- 《人工智能》机器学习 - 第6章感知机模型(一 理论讲解)
- 三大高级协议--http/dhcp/ftp
- 循环 条件 命名 运算符
- 计算机应用中英文缩写ai表示,2012浙江省全国计算机等级考试二级VB笔试试卷及参考答案考资料...
- HJLF-E1 DC220V【反时限电流继电器】
- 自制微电脑--学习其原理
热门文章
- setTimeout(〒︿〒) 请原谅我一直以来对你的忽视
- ff7重制版青魔法_狂父重制版发布+妖精的尾巴首次打折¥244+最终幻想4解锁国区新增中文...
- java8新日期时间类使用
- wps linux 字体_WPS Office:Linux 上的 Microsoft Office 的免费替代品 | Linux 中国
- umbrello 用户手册_别克君威车主必备:君威用户手册|君威使用说明书电子版|君威保养手册_搜狐汽车...
- 的write方法有哪些参数_Python笔记13:文件操作三件套:read,write,seek
- 使用python制作ArcGIS插件(1)工具介绍
- 关于JEECG中表单提交的中断与手动提交
- SpringMVC之“HelloWorld”起步
- golang中的切片及内存拷贝