首页 > 解决方案 > 在 Cython 并行化期间如何附加到列表中?

问题描述

我必须将一个变量共享到 Cython 并行上下文中。

我想做这样的事情:

from cython.parallel import prange, parallel
cdef list factorize(cdef int n, cdef int limit):
    cdef list factors
    cdef int p

    factors = []
    with cython.nogil, parallel():
        for p in prange(3, limit, 2):
            if p * p > n: break
            if n % p == 0: 
                factors.append(p)
                n = n // p
    if n > 1: factors.append(n)
    return factors

如何factors在并行上下文中附加到列表变量中?而且,为什么n // p没有gil我不能做手术呢?我可以用这种方式实现这个方法吗?

PS:这只是一个例子,但我在其他上下文中有相同的 for 循环,所以我想知道我是否可以并行化这种类型的 for 循环,如果可能的话,我该怎么做?

标签: parallel-processingcython

解决方案


:为什么没有我不能做手术?n // pGIL

出于某种原因,GIL 锁被用作重新[SERIAL]执行任何并发代码执行的手段,这主要防止(通过锁定避免)任何两个线程在尝试修改公共对象时竞争和碰撞(n- 是第一个这样的候选人,factors[]出于同样的原因是第二个)

不锁定
Global ........意味着除了我之外没有人拥有(或不拥有)全球受人尊敬的 GIL
I nterpereter ....是的,我们仍然生活在解释代码生态系统
Lock 中。 .............必须等待,直到确认我的 GIL 所有权,如果没有第一次拥有它,就无法继续修改​​对象

同时执行prange(3, limit, 2)- 许多代码执行路径,将headbang 尝试分配到int n(当然,重新关联,如果python pedantic)并且在尝试重新组织列表时遇到了同样的麻烦factors[],因为.append()- 方法需要在内部进行一些内部手术“活”——病人。

如果不是 GIL-lock 麻醉,为了片刻不动,当 GIL-owner 且只有 GIL-owner 可以拿工具切割和重组患者的内部状态时,只有在手术完成,为了让factors[]生活更进一步,在手术安全完成后释放GIL锁,如果许多外科医生切开内部静脉和其他任何东西,那么没有人会猜测内部状态会发生的折磨如此不愉快病人。

GIL 锁定只是防止了这场灾难性的大屠杀的发生,但代价是重新[SERIAL]调整所有手术操作......

如何在并行上下文中附加到因素列表变量中?

最好的方法是附加到私人修改/专门用于编写的对象中,然后sum_reduce在(现在主要是独立附加)并行部分完成工作之后“”它们。


推荐阅读