我正在使用 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
但我得到:
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 故意选择排除任何 Python 变量(包括 Cythoncdef class
es) 来自线程局部变量列表。Code https://github.com/cython/cython/blob/c492bab673fe7869d33149358ba184e7b4f01536/Cython/Compiler/Nodes.py#L8288
我怀疑这是故意避免引用计数问题 - 他们需要在循环结束时删除所有线程局部变量的引用计数(这不会是一个不可克服的问题,但可能是一个很大的变化) 。因此我认为它不太可能被修复,但文档更新可能会有所帮助。
解决方案是将循环体重构为一个函数,其中每个变量最终都有效地“本地”到函数中,这样就不会出现问题:
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()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)