Cython parallel prange 抛出编译器警告
Cython parallel prange throws a compiler warning
我是Cython初学者,我只是尝试玩一个玩具示例来体验cython并行循环功能prange
。这是我的示例代码 cy_sum_parallel.pyx
,它尝试使用 prange
.
简单地对二维数组求和
# distutils: extra_compile_args = -fopenmp
# distutils: extra_link_args = -fopenmp
cimport cython
from cython.parallel cimport prange
@cython.boundscheck(False)
@cython.wraparound(False)
cdef double sum_with_parallel(double[:,::1] arr_2d):
cdef:
unsigned int i, j, M, N
double partial_sum = 0.0
M = arr_2d.shape[0]
N = arr_2d.shape[1]
for i in prange(M, nogil=True):
for j in range(N):
partial_sum += arr_2d[i, j]
return partial_sum
import numpy as np
arr = np.ones(shape=(10000,10000), dtype=np.double, order='C')
def main():
return sum_with_parallel(arr)
最少 setup.py
脚本
from distutils.core import setup, Extension
from Cython.Build import cythonize
ext = Extension(name='cy_sum_parallel',
sources=['cy_sum_parallel.pyx'])
setup(ext_modules=cythonize(ext))
当我 运行 这是 setup.py
脚本时,它抛出以下编译器警告:
gcc -pthread -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/home/Jian/anaconda3/include/python3.4m -c cy_sum_parallel.c -o build/temp.linux-x86_64-3.4/cy_sum_parallel.o -fopenmp
cy_sum_parallel.c: In function ‘__pyx_f_15cy_sum_parallel_sum_with_parallel._omp_fn.0’:
cy_sum_parallel.c:1388:29: warning: ‘__pyx_v_j’ may be used uninitialized in this function [-Wmaybe-uninitialized]
#pragma omp for lastprivate(__pyx_v_j) firstprivate(__pyx_v_i) lastprivate(__pyx_v_i)
^
cy_sum_parallel.c:1316:7: note: ‘__pyx_v_j’ was declared here
int __pyx_v_j;
^
我想这个警告告诉我 j
已声明但未初始化。所以我的问题是 我应该对这个警告消息做些什么吗?以及如何?
编译后的代码似乎 运行 正确
import sys
sys.path.append('/home/Jian/Dropbox/Coding/Python/Cython/ex_parallel')
import cy_sum_parallel
%prun -s tottime -l 5 cy_sum_parallel.main()
与非并行版本相比,它的性能提升了 3 倍,这是 8 核机器上的预期结果。
非常感谢任何帮助。
您可以随时查看生成的 C 代码以检查上下文。如果要生成代码,请使用 cython -a <filename.pyx>
创建可浏览的 html 文件,或者仅 cython <filename.pyx>
就地生成 C 文件。
代码有点绕,使用了很多临时变量(指定__pyx_t_*
),但是看起来像这样
/* code snippet starts in an already quite nested set of for-loops */
#ifdef _OPENMP
#pragma omp for lastprivate(__pyx_v_j) firstprivate(__pyx_v_i) lastprivate(__pyx_v_i)
#endif /* _OPENMP */
for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_3; __pyx_t_2++){
{
__pyx_v_i = 0 + 1 * __pyx_t_2;
/* Initialize private variables to invalid values */
__pyx_v_j = ((unsigned int)0xbad0bad0);
__pyx_t_4 = __pyx_v_N;
for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) {
__pyx_v_j = __pyx_t_5;
/* etc */
我认为在这种情况下,如果循环大小为 0(这是生成消息的原因),变量 __pyx_v_j
将不会被初始化,但它不会在循环外使用,因此真的没关系。 (为了不占用太多,我省略了循环后的代码space,大家可以自己查一下!)
因此请忽略警告 - 这是一个错误的诊断。
我是Cython初学者,我只是尝试玩一个玩具示例来体验cython并行循环功能prange
。这是我的示例代码 cy_sum_parallel.pyx
,它尝试使用 prange
.
# distutils: extra_compile_args = -fopenmp
# distutils: extra_link_args = -fopenmp
cimport cython
from cython.parallel cimport prange
@cython.boundscheck(False)
@cython.wraparound(False)
cdef double sum_with_parallel(double[:,::1] arr_2d):
cdef:
unsigned int i, j, M, N
double partial_sum = 0.0
M = arr_2d.shape[0]
N = arr_2d.shape[1]
for i in prange(M, nogil=True):
for j in range(N):
partial_sum += arr_2d[i, j]
return partial_sum
import numpy as np
arr = np.ones(shape=(10000,10000), dtype=np.double, order='C')
def main():
return sum_with_parallel(arr)
最少 setup.py
脚本
from distutils.core import setup, Extension
from Cython.Build import cythonize
ext = Extension(name='cy_sum_parallel',
sources=['cy_sum_parallel.pyx'])
setup(ext_modules=cythonize(ext))
当我 运行 这是 setup.py
脚本时,它抛出以下编译器警告:
gcc -pthread -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/home/Jian/anaconda3/include/python3.4m -c cy_sum_parallel.c -o build/temp.linux-x86_64-3.4/cy_sum_parallel.o -fopenmp
cy_sum_parallel.c: In function ‘__pyx_f_15cy_sum_parallel_sum_with_parallel._omp_fn.0’:
cy_sum_parallel.c:1388:29: warning: ‘__pyx_v_j’ may be used uninitialized in this function [-Wmaybe-uninitialized]
#pragma omp for lastprivate(__pyx_v_j) firstprivate(__pyx_v_i) lastprivate(__pyx_v_i)
^
cy_sum_parallel.c:1316:7: note: ‘__pyx_v_j’ was declared here
int __pyx_v_j;
^
我想这个警告告诉我 j
已声明但未初始化。所以我的问题是 我应该对这个警告消息做些什么吗?以及如何?
编译后的代码似乎 运行 正确
import sys
sys.path.append('/home/Jian/Dropbox/Coding/Python/Cython/ex_parallel')
import cy_sum_parallel
%prun -s tottime -l 5 cy_sum_parallel.main()
与非并行版本相比,它的性能提升了 3 倍,这是 8 核机器上的预期结果。
非常感谢任何帮助。
您可以随时查看生成的 C 代码以检查上下文。如果要生成代码,请使用 cython -a <filename.pyx>
创建可浏览的 html 文件,或者仅 cython <filename.pyx>
就地生成 C 文件。
代码有点绕,使用了很多临时变量(指定__pyx_t_*
),但是看起来像这样
/* code snippet starts in an already quite nested set of for-loops */
#ifdef _OPENMP
#pragma omp for lastprivate(__pyx_v_j) firstprivate(__pyx_v_i) lastprivate(__pyx_v_i)
#endif /* _OPENMP */
for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_3; __pyx_t_2++){
{
__pyx_v_i = 0 + 1 * __pyx_t_2;
/* Initialize private variables to invalid values */
__pyx_v_j = ((unsigned int)0xbad0bad0);
__pyx_t_4 = __pyx_v_N;
for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) {
__pyx_v_j = __pyx_t_5;
/* etc */
我认为在这种情况下,如果循环大小为 0(这是生成消息的原因),变量 __pyx_v_j
将不会被初始化,但它不会在循环外使用,因此真的没关系。 (为了不占用太多,我省略了循环后的代码space,大家可以自己查一下!)
因此请忽略警告 - 这是一个错误的诊断。