【问题标题】:Program using parallelism crashing: Discarding owned Python object not allowed without gil使用并行性崩溃的程序:没有 gil 就不允许丢弃拥有的 Python 对象
【发布时间】:2021-01-19 02:51:47
【问题描述】:
    %%cython
from threading import Thread
import time
def countdown(n):
    while n > 0:
        n -= 1

COUNT = 10000000


start = time.time()
t1 = Thread(target=countdown,args=(COUNT/2,))
t2 = Thread(target=countdown,args=(COUNT/2,))
with nogil:
    t1.start();t2.start()
    t1.join();t2.join()
    
end = time.time()
print(end-start)

我在 Cython 文档网站上读到,几乎每个 Python 代码都可以在 Cython 中使用。众所周知,这是一个著名的 sn-p 来展示 Python 和 GIL 的局限性。我试图在 Cython 中重新创建一个解决方案。

但是,我在编译此代码时遇到了这个问题。

Error compiling Cython file:
------------------------------------------------------------
...

start = time.time()
t1 = Thread(target=countdown,args=(COUNT/2,))
t2 = Thread(target=countdown,args=(COUNT/2,))
with nogil:
    t1.start();t2.start()
           ^
------------------------------------------------------------

/Users/sanskar/.ipython/cython/_cython_magic_bb84bd2392afb02224d35c81782c007c.pyx:14:12: Discarding owned Python object not allowed without gil

Error compiling Cython file:
------------------------------------------------------------
...

从我的代码中可以看出,我对 Cython 还很陌生。我想就如何解决它提出一些建议。

【问题讨论】:

    标签: python c python-3.x types cython


    【解决方案1】:

    这是行不通的。

    线程库返回 Python 对象。要与他们互动,您需要 GIL。因此,您不能指望在没有 GIL 的情况下致电 .start().join()

    更有用的是用 nogil 块包装不需要 GIL 的函数部分。例如,countdown 中的循环可以在没有 GIL 的情况下轻松完成(实际上,C 编译器很有可能会发现这个循环完全没有意义并完全删除它,但这是一个单独的问题)

    def countdown(int n):
        with nogil:
            while n > 0:
                n -= 1
    

    这允许在没有 GIL 的情况下完成大部分工作,但需要在函数的开始和结束处保存 GIL。


    还有一个复杂的问题:常规 Python 代码偶尔会释放 GIL,以便在需要时允许其他线程运行。 Cython 通常不会(尽管它可能会调用 Python 代码,所以你不能依赖它)。因此,在 Cython 中编写 countdown 可能有意义,但不是启动线程的代码。

    我怀疑这不会是一个问题,但最好是安全的。

    【讨论】:

    • 嗨@DavidW。感谢您提供此解决方案。我这样做是因为我希望能够传递 nogil 指令中的函数。可以使用哪些其他方法来传递这些函数?简而言之:我想创建一个通用并行处理模板,我可以在其中传递自定义函数。这在 Cython 中可以实现吗?
    • 我不知道有什么办法,我也不太明白你为什么需要这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    • 2021-02-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多