跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • C 语言插件可以默认摆脱 Python 的 GIL 约束吗?为什么测试结果不是如此?
未分類
25 11 月 2020

C 语言插件可以默认摆脱 Python 的 GIL 约束吗?为什么测试结果不是如此?

C 语言插件可以默认摆脱 Python 的 GIL 约束吗?为什么测试结果不是如此?

資深大佬 : black11black 3

如题,最近用 cyhton 写了个加速插件,给 python 中的某个模块加速了两百倍左右,效果十分满意。

于是又给算法复杂度加了十倍,这次 c 也顶不住了,单个函数调用时间一分钟左右。

于是想到了多线程,因为 python 进入 3.6 时代后异步逐渐完善,日常里使用 python 多线程的地方主要还是在 IO,通过异步 IO 复用解决得很开心,所以很久没有用过多线程模块了。

按照我记忆中的只是,python 的 GIL 机制是,如果你调用 C 插件的话是会默认释放 GIL 锁的,也就是说应该是原生使用多线程,并且在每个线程中调用 c 插件的话,它应该是可以利用多核心的,于是写了个简单小测试,但是结果不太对。我最终的结果还是顺序执行的时间,并没有利用多核心加速,是哪里做错了吗,还是我记错了,带佬来说一下。

简单 demo 代码如下:

# timer.py import zhishu import time from threading import Thread  thread_list = [Thread(target = zhishu , args = (150000 , )) for _ in range(8)]  st_time = time.time() for _ in thread_list:     _.start() for _ in thread_list:     _.join() print(time.time() - st_time) 

这个简单 demo 创建了 8 个线程,每个线程调用一个名叫 zhishu 的由 cython 编写的函数,这个函数的作用是计算 n 以内质数数量,我本机上单次调用大概需要 2s,我有 8 颗核心,理论上我期望他在 2s 内完成全部计算,但是最终得到的结果却是 16s

cython 代码: 一个简单的质数计算器

# zhishu.pyx import cython  def zhishu(n):     cdef cython.int count = 0     cdef cython.int i , j , nn     nn = <cython.int> n      for i in range(2 , n):         for j in range(2 , i):             if (i%j == 0):                 break         else:             count += 1     return count 

感谢!

大佬有話說 (5)

  • 資深大佬 : agegcn

    cython 有 nogil 的选项。因为 cython 里也会有 python object,所以需要手动释放 gil 锁

  • 資深大佬 : westoy

    最简单的方案就是最里面的 for j 的 range 用 cython.parallel.prange(…, nogil=True)替换掉, 能用多核, 不过效果也有限

    建议写个原生 c 方案, 然后套个函数入口, 把参数转成原生类型后套到 with nogil 里面

  • 主 資深大佬 : black11black

    @westoy
    @agegcn 所以是 cython 的问题,用 ctypes 的话就可以直接释放 gil 了吗?我记得很久以前在做 gil 实验的时候用 c 就解决了,没有什么做了特殊处理的印象。印象中当初 ctypes 折腾 c++stl 容器搞了很长时间没搞明白,就放弃这条路线了。现在直接手动编译 dll 的问题也在于 ctypes 折腾 stl 容器,以及把 python 的 list 映射到 vector 之类的这类输入输出的问题,中间处理倒是完全可以用 c++重写。

    试了试 with nogil 编译不通过啊,不知道问题在哪里,没感觉有什么非 C 内容啊。

  • 資深大佬 : jones2000

    c 内部开线程或并行计算. 外部 py 只做简单的调度和数据准备工作.

  • 資深大佬 : helloworld000

    既然速度真的很重要,建议用 c++重写这个 module,然后用 pybind11 来给其他 python modules 调用

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具