减少cython并行中的数组

Posted

技术标签:

【中文标题】减少cython并行中的数组【英文标题】:Reduction of array in cython parallel 【发布时间】:2016-04-10 18:02:05 【问题描述】:

我有一个需要包含不同事物总和的数组,因此我想对其每个元素执行归约。 代码如下:

cdef int *a=<int *>malloc(sizeof(int) * 3)
for i in range(3):
    a[i]=1*i
cdef int *b
for i in prange(1000,nogil=True,num_threads=10):
    b=res() #res returns an array initialized to 1s
    with gil: #if commented this line gives erroneous results 
        for k in range(3):
            a[k]+=b[k]
for i in range(3):
    print a[i]

直到有 with gil 代码运行良好,否则会给出错误的结果。 如何在不使用 gil 的情况下处理数组每个元素的减少,因为我认为 gil 会阻塞其他线程

【问题讨论】:

cdef int k了吗? 【参考方案1】:

在实践中通常的减少方式是对每个线程单独进行求和,然后在最后将它们相加。您可以手动执行此操作,例如

cdef int *b
cdef int *a_local # version of a that is duplicated by each thread
cdef int i,j,k

# set up as before
cdef int *a=<int *>malloc(sizeof(int) * 3)
for i in range(3):
    a[i]=1*i

# multithreaded from here
with nogil, parallel(num_threads=10):
    # setup and initialise a_local on each thread
    a_local = <int*>malloc(sizeof(int)*3)
    for k in range(3):
        a_local[k] = 0

    for i in prange(1000):
        b=res() # Note - you never free b
                # this is likely a memory leak....

        for j in range(3):
            a_local[j]+=b[j]

    # finally at the end add them all together.
    # this needs to be done `with gil:` to avoid race conditions 
    # but it isn't a problem
    # because it's only a small amount of work being done
    with gil:
        for k in range(3):
            a[k] += a_local[k]
    free(a_local)

【讨论】:

和我给出的例子有什么不同?? a_local 是为每个线程创建的,并在不使用 gil 的情况下在主循环中汇总(因此这可以并行发生)。最后,将每个线程的a_locals 添加在一起。这需要 gil,但每个线程只需要发生一次(而不是每个循环一次),因此成本很小。

以上是关于减少cython并行中的数组的主要内容,如果未能解决你的问题,请参考以下文章

cython中的二维数组切片

在cython中并行化for循环:超越prange

Cython 中的这个声明是啥? cdef PyObject **工人。它是指向指针的指针吗?

Cython 似乎通过减少时间分析器而不是核心代码的开销来提供加速?

在 Cython 的结构中使用指针数组

python怎么使用cython