设为首页 收藏本站
查看: 878|回复: 0

[经验分享] Cython 0.15,用 OpenMP 并行多核加速 Python!

[复制链接]

尚未签到

发表于 2017-5-7 11:11:50 | 显示全部楼层 |阅读模式
  赖勇浩(http://laiyonghao.com)
注:
0、读懂这篇文章需要了解 OpenMP 基本用法。
1、读懂这篇文章需要了解 GIL 基本概念。
2、基本上是这篇的翻译:http://docs.cython.org/src/userguide/parallelism.html,标题是我自己取的,如有错漏、不明,敬请参详原文。
3、本篇不是使用 cython.parallel 的指南(或手册),仅作信息传播之用。
4、我之前翻译过一篇文章《OpenMP与C++:事半功倍地获得多线程的好处》有助于理解这篇文章,见:上(http://blog.csdn.net/lanphaday/article/details/1503817),下(http://blog.csdn.net/lanphaday/article/details/1507834)。
DSC0000.png Cython 0.15 新增了 cython.parallel 模块,实现对原生并行编程的支持。现在只支持 OpenMP,以后会加入更多的后端支持。需要注意的是并行是运行在释放了 GIL 的环境下的。

cython.parallel.prange([start], stop[, step], nogil=False, schedule=None)
  此函数并行循环,OpenMP 自动构建线程池,并根据指定的调度方案分派作业给这些线程。step 参数不可为 0,如果 nogil 参数为 true,那么这个循环就会被包装在一个 nogil 环境中。shedule 参数支持 static/dynamic/guided/auto/runtime 等 OpenMP 中定义的调度机制。
thread-locality 和 reduction 是从变量进来推断决定的。在 prange 块中被赋值的变量,会被看作 lastprivate,意思是这个变量的值会是最后一次迭代的值。如果对变量使用了原地操作符,那它会被看作 reduction,意思是每条线程都拷贝了一个私有变量,然后在循环结束后应用这个操作符,并赋值给原来的变量。索引变量总是 lastprivate,而在并行块中被赋值的变量都会被看作 private,而且在离开并行块后不可用,因为无法确定它的最后的值。(译注:对这两段理解不能的话,需要阅读 OpenMP 相关文档)。
下面是一个关于 reduction 的例子:

from cython.parallel import prange, parallel, threadidcdef int icdef int sum = 0for i in prange(n, nogil=True):sum += iprint sum再来一个共享 numpy 数组的例子:
from cython.parallel import *def func(np.ndarray[double] x, double alpha):cdef Py_ssize_t ifor i in prange(x.shape[0]):x = alpha * xcython.parallel.parallel()
  可以在 with 语句中使用这个指令来实现代码序列的并行执行。这在为 prange 准备 thread-local 的缓冲区时非常有用。内含的 prange 将成为不并行的工作共享循环,所以一切在并行 section 中被赋值的变量在 prange 中也是 private。所有并行块中的 private 变量在离开并行块后都不可用。
thread-local 缓冲的例子:

from cython.parallel import *from libc.stdlib cimport abort, malloc, freecdef Py_ssize_t idx, i, n = 100cdef int * local_bufcdef size_t size = 10with nogil, parallel():local_buf = <int *> malloc(sizeof(int) * size)if local_buf == NULL:abort()# populate our local buffer in a sequential loopfor idx in range(size):local_buf = i * 2# share the work using the thread-local buffer(s)for i in prange(n, schedule='guided'):func(local_buf)free(local_buf)以后 sections 将支持并行块,这样可以把 sections 的代码分配给多个线程执行。
cython.parallel.threadid()
  返回线程 ID,对于 n 个线程,它们的 ID 范围是 [0, n)。

编译
  要启用 OpenMP 支持,需要把 C 或 C++ 编译器的 OpenMP 开关打开,gcc 适用的 setup.py 如下:

from distutils.core import setupfrom distutils.extension import Extensionfrom Cython.Distutils import build_extext_module = Extension("hello",["hello.pyx"],extra_compile_args=['-fopenmp'],extra_link_args=['-fopenmp'],)setup(name = 'Hello world app',cmdclass = {'build_ext': build_ext},ext_modules = [ext_module],)打断
  nogil 模式下的并行的 with 和 prange 块支持 break、continue 和 return。此外,还能够在这些块中使用 with gil 块,也可以抛出异常。但是,因为使用了 OpenMP,不能跳出了事,最好还是退出程序。以 prange() 为例,在第一次 return、break 或抛出异常后,所有线程的每一次循环都会跳过。所以如果有多个值应当返回时该返回哪个值是没有定义的,因为迭代本身是没有特定的顺序的:

from cython.parallel import prangecdef int func(Py_ssize_t n):cdef Py_ssize_t ifor i in prange(n, nogil=True):if i == 8:with gil:raise Exception()elif i == 4:breakelif i == 2:return i上例中到底是抛出异常,还是简单地 break 又或者返回 2,是没有定义的(不确定的)。
嵌套并行
  因为 gcc 的一个 bug,现在嵌套并行被禁用掉了,不过,你可以在一个并行段中调用含有并行段的函数。

参考资料
  [1] http://www.openmp.org/mp-documents/spec30.pdf
[2] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49897

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-374131-1-1.html 上篇帖子: Python对XML的处理 下篇帖子: 在python中使用多线程下载网页
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表