在cython中使用prange时如何处理cython中的关键部分?
#pragma omp critical 是否允许?
use lib ('./t/lib/');
use strict;
use warnings;
use Template;
use Test::More tests => 1;
# options/configuration for template
#my $config = {
#PRE_PROCESS => 1, # means the templates processed can use the same global vars defined earlier
#INTERPOLATE => 1,
#EVAL_PERL => 1,
# RELATIVE => 1,
# OUTPUT_PATH => './out',
# };
my $template = Template->new();
# input string
my $text = "This is string number [% num %] .";
# template placeholder variables
my $vars = {
num => "one",
};
my $output = shift;
my $expected_output = "This is string number one .";
# processes input string and inserts placeholder values
$template->process(\$text, $vars, \$output)
|| die "Template process failed: ", $template->error(), "\n";
# If process method is executed successfully it should have a return value of 1
diag($template->process(\$text, $vars, \$output));
# compares actual output with the expected output
is($output, $expected_output);
答案 0 :(得分:0)
要处理关键部分,可以使用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)
.
.
.
答案 1 :(得分:0)
我已经找到了使用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)
如果我们可以在Cython中将C ++对象分配给堆栈,则可以忽略del lck
并使其变得更好。很抱歉,Cython禁止使用此afaik。使用上述方法,存在忘记解锁的风险,我认为人们可以直接使用互斥锁(我认为是使用mtx.lock()
来代替lock_guard
。
我使用recursive_mutex,因为用例通常需要嵌套/递归锁。只是作为笔记。
我只是准备了这个解决方案,我不能说建议使用openmp还是C ++ 11。
编辑:人们可以使用共享指针下到一行并保证“更安全”的解锁(在上面的示例中,适当时添加/替换这些行):
from libcpp.memory cimport shared_ptr, make_shared
[...]
cdef shared_ptr[lock_guard[recursive_mutex]] lck = make_shared[lock_guard[recursive_mutex]](mtx)
但是,看起来并不好看。