我开始搞乱并行编程和cython / openmp,我有一个简单的程序,使用prange对数组进行求和:
import numpy as np
from cython.parallel import prange
from cython import boundscheck, wraparound
@boundscheck(False)
@wraparound(False)
def parallel_summation(double[:] vec):
cdef int n = vec.shape[0]
cdef double total
cdef int i
for i in prange(n, nogil=True):
total += vec[i]
return total
使用setup.py文件似乎正常。但是,我想知道是否可以调整此功能并对处理器正在执行的操作进行更多控制。
假设我有4个处理器:我想将矢量分成4个部分,然后让每个处理器在本地添加元素。然后在最后,我可以组合每个处理器的结果来获得总和。从cython文档中,我无法收集这样的事情是否可能(文档有点稀疏)。
如果有人可以使用cython / openmp解释是否/如何完成这样的事情,或者可能帮助找到一些相关的例子(很难在网上找到简单的例子),我感激不尽。
答案 0 :(得分:1)
我想将矢量分成4个部分,然后让每个处理器在本地添加元素。然后在最后,我可以组合每个处理器的结果来获得总和。
这正是这里发生的事情。 Cython可以从您想要进行减少的现场操作中推断出来。 OpenMP将使用total
变量的私有(零初始化)副本实现并行循环,并在循环结束时将它们全部添加到total
。
在生成的C中,这看起来像这样:
#pragma omp parallel
{
#pragma omp for firstprivate(__pyx_v_i) lastprivate(__pyx_v_i) reduction(+:__pyx_v_total)
for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_3; __pyx_t_2++){
{
__pyx_v_i = (int)(0 + 1 * __pyx_t_2);
__pyx_t_4 = __pyx_v_i;
__pyx_v_total = (__pyx_v_total + (*((double *) ( /* dim=0 */ (__pyx_v_vec.data + __pyx_t_4 * __pyx_v_vec.strides[0]) ))));
}
}
}
您只需启用OpenMP as described here。
您应该在代码中更改的一件事是初始化total = 0
,否则它只是一个可能包含垃圾的单元化C变量。