Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading Cython并行prange线程位置?_Multithreading_Parallel Processing_Cython - Fatal编程技术网

Multithreading Cython并行prange线程位置?

Multithreading Cython并行prange线程位置?,multithreading,parallel-processing,cython,Multithreading,Parallel Processing,Cython,我正在使用prange对如下列表进行迭代: from cython.parallel import prange, threadid cdef int tid cdef CythonElement tEl cdef int a, b, c # elList: python list of CythonElement instances is passed via function call for n in prange(nElements, schedule='dynamic', nog

我正在使用prange对如下列表进行迭代:

from cython.parallel import  prange, threadid

cdef int tid
cdef CythonElement tEl
cdef int a, b, c

# elList: python list of CythonElement instances is passed via function call
for n in prange(nElements, schedule='dynamic', nogil=True):
    with gil:
        tEl = elList[n]
        tid =  threadid()
        a = tEl.a
        b = tEl.b
        c = tEl.c 

        print("thread {:} elnumber {:}".format(tid, tEl.elNumber))

   #nothing is done here

    with gil:
        print("thread {:} elnumber {:}".format(tid, tEl.elNumber))

    # some other computations based on a, b and c here ...
thread 0 elnumber 1
thread 1 elnumber 2
thread 2 elnumber 3
thread 3 elnumber 4
thread 0 elnumber 1
thread 1 elnumber 2
thread 2 elnumber 3
thread 3 elnumber 4
我希望得到如下输出:

from cython.parallel import  prange, threadid

cdef int tid
cdef CythonElement tEl
cdef int a, b, c

# elList: python list of CythonElement instances is passed via function call
for n in prange(nElements, schedule='dynamic', nogil=True):
    with gil:
        tEl = elList[n]
        tid =  threadid()
        a = tEl.a
        b = tEl.b
        c = tEl.c 

        print("thread {:} elnumber {:}".format(tid, tEl.elNumber))

   #nothing is done here

    with gil:
        print("thread {:} elnumber {:}".format(tid, tEl.elNumber))

    # some other computations based on a, b and c here ...
thread 0 elnumber 1
thread 1 elnumber 2
thread 2 elnumber 3
thread 3 elnumber 4
thread 0 elnumber 1
thread 1 elnumber 2
thread 2 elnumber 3
thread 3 elnumber 4
但我得到:

thread 1 elnumber 1
thread 0 elnumber 3
thread 3 elnumber 2
thread 2 elnumber 4
thread 3 elnumber 4
thread 1 elnumber 2
thread 0 elnumber 4
thread 2 elnumber 4

那么,线程局部变量tEl会被线程覆盖吗?我做错了什么?谢谢大家!

Cython提供基于线程的并行性。不能保证线程的执行顺序,因此
线程的值是无序的


如果希望
tEl
对线程私有,则不应全局定义它。尝试在prange中移动
cdef CythoneElement tEl
。请参阅(关于私有变量的部分)。

看起来Cython故意选择从线程局部变量列表中排除任何Python变量(包括Cython
cdef类)

我怀疑这是故意为了避免引用计数问题——他们需要在循环结束时删除所有线程局部变量的引用计数(这不是一个无法克服的问题,但可能是一个很大的变化)。因此,我认为它不太可能被修复,但文档更新可能会有所帮助

解决方案是将循环体重构为一个函数,其中每个变量实际上都是函数的“局部”变量,这样就不会出现问题:

cdef f(CythonElement tEl):
    cdef int tid
    with nogil:
        tid = threadid()
        with gil:
            print("thread {:} elnumber {:}".format(tid, tEl.elNumber))

        with gil:
            print("thread {:} elnumber {:}".format(tid, tEl.elNumber))

   # I've trimmed the function a bit for the sake of being testable

# then for the loop:
for n in prange(nElements, schedule='dynamic', nogil=True):
    with gil:
        f()

谢谢你的快速回复。但是,编译给了我:>>>>这里不允许cdef语句好的,我打开了很多选项卡,我找不到我看到cdef移动的地方。在阅读您的示例时,我没有看到函数。通常,cython文件被编译成模块,并调用生成的函数。代码在完整文件之上吗?实际上它在链接中。Search“cdef w=Worker(n)#block scoped cdef”tEl是cython扩展(cdef类)的一个实例。后来调用了它的一个nogil方法,但这与发布的问题无关。基本上,这个代码段会产生错误。>>>实际上它在链接中。搜索“cdef w=Worker(n)#块作用域cdef您是对的。它似乎没有使
tEl
线程成为本地线程(查看生成的C文件,并搜索
lastprivate
进行检查)。如果您将其更改为基本类型(如
double
)它对Cython对象类型起作用,但似乎不起作用。我不知道一个明显的解决方案,但据我所知,可能值得在githubOk上安装一个bug。不幸的是,似乎无法并行调用cdef扩展。目前重构为纯cdef函数调用并不现实。在您的示例中,f()声明时没有nogil标志,因此不是并行执行的?如果调用refcount tEl,则在开始和结束时需要gil。它可以释放内部的gil,并且该位将并行运行。它应该不会比您问题中的代码更糟糕(显然在这个玩具示例中几乎没有“无gil”工作)。