使用并行崩溃的程序:在没有gil的情况下不允许丢弃拥有的Python对象

使用并行崩溃的程序:在没有gil的情况下不允许丢弃拥有的Python对象,python,c,python-3.x,types,cython,Python,C,Python 3.x,Types,Cython,我在Cython文档网站上读到,几乎所有python代码都可以在Cython中使用。正如我们所知,这是一个演示Python和GIL局限性的著名片段。我试图在Cython中重新创建一个解决方案 然而,我在编译这段代码时遇到了这个问题 %%cython from threading import Thread import time def countdown(n): while n > 0: n -= 1 COUNT = 10000000 start =

我在Cython文档网站上读到,几乎所有python代码都可以在Cython中使用。正如我们所知,这是一个演示Python和GIL局限性的著名片段。我试图在Cython中重新创建一个解决方案

然而,我在编译这段代码时遇到了这个问题

    %%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对象。要与他们互动,你需要GIL。因此,在没有GIL的情况下,您不能期望调用
.start()
.join()

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

这允许在没有GIL的情况下完成大部分工作,但需要在功能开始和结束时保持GIL


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


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

Hi@DavidW。感谢您提供此解决方案。我这样做是因为我希望能够传递
nogil
指令中的函数。可以使用哪些其他方法传入这些函数?简而言之:我想创建一个通用的并行处理模板,在其中我可以传递自定义函数。这在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:
------------------------------------------------------------
...
def countdown(int n):
    with nogil:
        while n > 0:
            n -= 1