我有以下Cython
代码:
from cython import parallel
from libc.stdio cimport printf
cdef extern from "unistd.h" nogil:
int usleep(int);
def test_func():
cdef int var = -1
with nogil, parallel.parallel(num_threads=4):
var = parallel.threadid()
usleep(100000)
printf("Var: %d\n", var)
在python3
控制台中编译并启动后,我得到:
>>> import test
>>> test.test_func()
Var: 3
Var: 0
Var: 2
Var: 1
这意味着,每个线程都有自己的地址空间。
但是,我希望C++
OpenMP
行为,重复此行为:
#include "omp.h"
#include <stdio.h>
#include <unistd.h>
int main() {
int v=-1;
omp_set_num_threads(4);
#pragma omp parallel
{
v=omp_get_thread_num();
usleep(100000);
printf("Var: %d\n", v);
}
return(0);
}
输出如下内容:
Var: 3
Var: 3
Var: 3
Var: 3
因此,问题:是否可以在Cython
并行块中获得共享地址空间?
答案 0 :(得分:1)
这有点像一种hacky方式,但使用指向var
的指针,你看起来能够欺骗它
def test_func2():
cdef int var = -1
cdef int* var_ptr = &var
with nogil, parallel.parallel(num_threads=4):
var_ptr[0] = parallel.threadid()
usleep(100000)
printf("Var: %d\n", var)
如果您查看生成的C代码,那么test_func
(您的版本)会给出行
#pragma omp parallel private(__pyx_v_var) num_threads(4)
而test_func2
给出了
#pragma omp parallel num_threads(4)
我认为这是有效的,因为你没有直接分配给它,所以Cython没有为什么私有的常规规则。这里有一个风险 - 如果Cython的未来版本变得更聪明并使var_ptr
变为私有,那么它将不会在并行部分的开始处初始化(所以要小心并检查它正在做什么!)。