数组运算加速是至关科学计算重要的领域,本节我们以一个简单函数为例,使用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[:] adouble[:] 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_高效数组操作相关推荐

  1. 『python爬虫』26. selenium与超级鹰处理复杂验证码的处理(保姆级图文)

    目录 1. 图片选择类验证码 2. 滑块验证码 3. 滑块出错,不加载 总结 欢迎关注 『python爬虫』 专栏,持续更新中 欢迎关注 『python爬虫』 专栏,持续更新中 1. 图片选择类验证码 ...

  2. 拼写单词 给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars。 假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符

    力扣1160. 拼写单词 给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars. 假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字 ...

  3. 『python爬虫』16. 多线程与多进程(保姆级图文)

    目录 多线程 1. 什么是多线程? 2. 串行模式 3. 多线程 3.1 多线程方法写法 3.2 多线程方法带参数 3.3 多线程类写法 多进程 1. 什么是多进程 欢迎关注 『python爬虫』 专 ...

  4. [转载] python+opencv图像处理:numpy数组操作

    参考链接: Python中的numpy.pv 图片以矩阵的形式存在电脑里,需要用到数组操作来完成对图像的处理 常用的有两个API: zeros和ones 1 np.ones(size) 可以创建任意维 ...

  5. python观察日志(part26)--numpy数组操作

    学习笔记,仅供参考,有错必究 数组操作 # 垂直方向和并数组 arr1 = np.array([[1, 2, 3], [0, 0, 1]]) arr2 = np.array([[4, 5, 6], [ ...

  6. 『python思考』关于列表的浅复制和深复制的理解

    >>> mylist1 = [1, 2, 3, 4] >>> myl = mylist1 >>> myl [1, 2, 3, 4] >> ...

  7. python数据分析做什么作业好_知识星球 | 说说我为什么要做『python数据分析』社群...

    过去一段时间,很多人会问我: "现在的工作没有前途,该如何转行?" "我知道数据时代已经来了,我该如何学习,不让自己落伍?" "数据分析适用于生活和工 ...

  8. 『Python × C++』函数传参机制学习以及对比

    一.Python函数传参 在python中,函数传参实际上传入的是变量的别名,由于python内在的变量机制(名称和变量值相互独立),只要传入的变量不可变(tuple中的元素也要是不可变的才行),那么 ...

  9. 『Python基础』第三节:变量和基础数据类型

    一. 变量 1. 变量是什么? 变量,是指把程序运行的中间结果临时的存在内存里,以便后续的代码调用,其值可以修改. 在python中,当变量被使用时,在内存里将产生两个动作,一是开辟指定地址的空间,二 ...

最新文章

  1. 服务端如何识别是selenium在访问以及解决方案参考二
  2. sudo出现sudo:must be setuid root问题的解决方法
  3. js data日期初始化的5种方法 [转]
  4. java小票_Java编程打印购物小票实现代码
  5. 线程魔术技巧:Java线程可以做的5件事
  6. WebPart的使用
  7. 从Slice_Header学习H.264(三.2)--相关细节之 参考图像列表
  8. 障碍期权定价 python_python障碍式期权定价公式
  9. python面向对象编程思想_面向对象编程思想及其特点
  10. 见山只是山 见水只是水——提升对继承的认识
  11. dd dt标签 显示与隐藏
  12. 我用 python 做了款可开淘宝店赚钱的工具
  13. 如何使用uni-app做一个音乐播放器
  14. 安卓APP开发发展趋势与前景
  15. 《人工智能》机器学习 - 第6章感知机模型(一 理论讲解)
  16. 三大高级协议--http/dhcp/ftp
  17. 循环 条件 命名 运算符
  18. 计算机应用中英文缩写ai表示,2012浙江省全国计算机等级考试二级VB笔试试卷及参考答案考资料...
  19. HJLF-E1 DC220V【反时限电流继电器】
  20. 自制微电脑--学习其原理

热门文章

  1. setTimeout(〒︿〒) 请原谅我一直以来对你的忽视
  2. ff7重制版青魔法_狂父重制版发布+妖精的尾巴首次打折¥244+最终幻想4解锁国区新增中文...
  3. java8新日期时间类使用
  4. wps linux 字体_WPS Office:Linux 上的 Microsoft Office 的免费替代品 | Linux 中国
  5. umbrello 用户手册_别克君威车主必备:君威用户手册|君威使用说明书电子版|君威保养手册_搜狐汽车...
  6. 的write方法有哪些参数_Python笔记13:文件操作三件套:read,write,seek
  7. 使用python制作ArcGIS插件(1)工具介绍
  8. 关于JEECG中表单提交的中断与手动提交
  9. SpringMVC之“HelloWorld”起步
  10. golang中的切片及内存拷贝