cython中的关键部分

时间:2016-04-15 17:55:11

标签: python c++ openmp cython critical-section

在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);

2 个答案:

答案 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)

但是,看起来并不好看。