我已经开始研究并行编程和 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
变量的私有(private)(零初始化)副本实现并行循环,并在循环结束时将它们全部添加到 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 变量。
关于python - 求和运算的本地并行计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42335427/