Reputation: 24742
I am a Cython beginner and I just try to play with a toy example to get an experience of cython parallel loop feature prange
. Here is my sample code cy_sum_parallel.pyx
which attempts to simply sum a 2-D array using 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)
with a minimum setup.py
script
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))
When I run this the setup.py
script, it throws the following compiler warnings:
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;
^
I presume that this warning tells me j
is declared but not initialized. So my question is Shall I do something to this warning message? and how?
The compiled code does seem to run properly
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()
and it gives a performance boost of 3 over non-parallel version, which is an expected result on a 8-core machine.
Any help is highly appreciated.
Upvotes: 0
Views: 569
Reputation: 30909
You can always look at the generated C code to check the context. If you want to generate the code either use cython -a <filename.pyx>
to create a browsable html file, or just cython <filename.pyx>
to generate a C file in place.
The code is a little convoluted, and uses a lot of temporary variables (designated __pyx_t_*
), but looks like this
/* 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 */
I think in this case the variable __pyx_v_j
won't be initialised if the size of the loop is 0 (which is what generates the message), but it isn't used outside the loop so that really doesn't matter. (I've omitted the code after the loop so as not to take up too much space, but you can check yourself!)
Therefore ignore the warning - it's a false diagnostic.
Upvotes: 1