Возможно, в Cython есть способы достичь того, чего вы хотите, однако я считаю, что проще использовать OpenMP из C / C ++ и вызывать функциональность из Cython (благодаря C -verbatim-code начиная с Cython 0.28 это довольно удобно).
Ясно одно: для достижения вашей цели вам нужна какая-то синхронизация между потоками, которая может повлиять на производительность. Моя стратегия проста: каждый поток сообщает «выполнено», все выполненные задачи регистрируются, и их количество время от времени сообщается. Количество зарегистрированных задач защищено с помощью мьютекса / блокировки :
%%cython -c=/openmp --link-args=/openmp
cdef extern from * nogil:
r"""
#include <omp.h>
#include <stdio.h>
static omp_lock_t cnt_lock;
static int cnt = 0;
void reset(){
omp_init_lock(&cnt_lock);
cnt = 0;
}
void destroy(){
omp_destroy_lock(&cnt_lock);
}
void report(int mod){
omp_set_lock(&cnt_lock);
// start protected code:
cnt++;
if(cnt%mod == 0){
printf("done: %d\n", cnt);
}
// end protected code block
omp_unset_lock(&cnt_lock);
}
"""
void reset()
void destroy()
void report(int mod)
from cython.parallel import prange
def prange_with_report(int n):
reset() # reset counter and init lock
cdef int index
for index in prange(n, nogil = True, num_threads = 5):
report(n//10)
destroy() # release lock
Теперь вызов: prange_with_report(100)
напечатает done: 10\n
, done: 20\n
, ..., done: 100\n
.
В качестве небольшой оптимизации report
можно вызывать не для каждого index
, а только, например, для index%100==0
- это будет меньше влиять на производительность, но и отчетность будет менее точной .