Cython 中的共享地址 space

Shared address space in Cython

我有以下 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

也就是说,每个线程都有自己的地址space。

但是,我想要 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 个并行块中获得共享地址 space?

这样做有点笨拙,但是使用指向 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 设为私有,那么它不会在并行部分开始时被初始化(所以要小心并检查它在做什么!)。