2015-11-10 2 views
1

У меня есть следующий 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 

Это означает, что каждый поток имеет свое собственное адресное пространство.

Однако, я хотел бы иметь 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 параллельных блоков?

ответ

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 приватной, тогда она не будет инициализирована в начале параллельного раздела (так что будьте осторожны и проверьте, что он делает!).

Смежные вопросы