我开始搞乱并行编程和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完成这样的事情,或者可能帮助找到一些相关的例子(很难在网上找到简单的例子).
最佳答案
I want to split the vector to be summed into 4 parts, and then have each processor locally add the elements inside. Then at the end, I can combine the results from each processor to get the total sum.
这正是这里发生的事情. 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变量.