在使用Cython中的prange时,如何处理关键部分?
#pragma omp critical 能否使用?
for e in prange(num,nogil=True,num_threads=4):
.
.
.
#pragma omp critical
cs
.
.
.
end_for
在使用Cython中的prange时,如何处理关键部分?
#pragma omp critical 能否使用?
for e in prange(num,nogil=True,num_threads=4):
.
.
.
#pragma omp critical
cs
.
.
.
end_for
要处理关键部分,您可以使用OpenMP锁。为此,请使用以下导入:
cimport openmp
然后进行初始化
cdef openmp.omp_lock_t lock
openmp.omp_init_lock(&lock)
with nogil, cython.boundscheck(False), cython.wraparound(False):
for i in parallel.prange(n, schedule = 'static',
num_threads = num_threads):
.
.
.
openmp.omp_set_lock(&lock)
cs
openmp.omp_unset_lock(&lock)
.
.
.
我找到了另一个解决方案,使用Cython和C++11,而不是像Okason的回答中那样使用openmp。
cdef extern from "<mutex>" namespace "std" nogil:
cdef cppclass recursive_mutex:
pass
cdef cppclass lock_guard[T]:
lock_guard(recursive_mutex mm)
cdef recursive_mutex mtx
cdef void someFun() nogil:
# lock_guard locks the mutex when it is created
cdef lock_guard[recursive_mutex]* lck = new lock_guard[recursive_mutex](mtx)
# do something thread-safely
del lck
# lock_guard unlocks the mutex when it is deleted
for ii in prange(4, nogil=True, num_threads=2):
someFun(ii)
del lck
,并且在我看来会更好一些;不幸的是,据我所知,Cython不允许这样做。使用上述方法存在忘记解锁的风险,我认为可以直接使用互斥锁(使用mtx.lock()
)而不是lock_guard
。from libcpp.memory cimport shared_ptr, make_shared
[...]
cdef shared_ptr[lock_guard[recursive_mutex]] lck = make_shared[lock_guard[recursive_mutex]](mtx)
虽然看起来不太好看。