Commit 17d04e6d authored by Mark Florisson's avatar Mark Florisson Committed by Vitja Makarov

Disallow nested parallel blocks and propagate sharing attributes

parent 300120ee
This diff is collapsed.
......@@ -978,6 +978,10 @@ class ParallelRangeTransform(CythonTransform, SkipDeclarations):
# Keep track of whether we are in a parallel range section
in_prange = False
# One of 'prange' or 'with parallel'. This is used to disallow closely
# nested 'with parallel:' blocks
state = None
directive_to_node = {
u"cython.parallel.parallel": Nodes.ParallelWithBlockNode,
# u"cython.parallel.threadsavailable": ExprNodes.ParallelThreadsAvailableNode,
......@@ -1070,9 +1074,16 @@ class ParallelRangeTransform(CythonTransform, SkipDeclarations):
# There was an error, stop here and now
return None
if self.state == 'parallel with':
error(node.manager.pos,
"Closely nested 'with parallel:' blocks are disallowed")
self.state = 'parallel with'
self.visit(node.body)
self.state = None
newnode = Nodes.ParallelWithBlockNode(node.pos, body=node.body)
else:
newnode = node
......@@ -1088,6 +1099,7 @@ class ParallelRangeTransform(CythonTransform, SkipDeclarations):
was_in_prange = self.in_prange
self.in_prange = isinstance(node.iterator.sequence,
Nodes.ParallelRangeNode)
previous_state = self.state
if self.in_prange:
# This will replace the entire ForInStatNode, so copy the
......@@ -1104,11 +1116,13 @@ class ParallelRangeTransform(CythonTransform, SkipDeclarations):
error(node.target.pos,
"Can only iterate over an iteration variable")
self.visit(node.body)
self.state = 'prange'
self.visit(node.body)
self.state = previous_state
self.in_prange = was_in_prange
self.visit(node.else_clause)
self.visit(node.else_clause)
return node
def ensure_not_in_prange(name):
......
......@@ -30,6 +30,12 @@ with nogil, cython.parallel.parallel:
for x[1] in prange(10):
pass
for x in prange(10):
pass
with cython.parallel.parallel:
pass
_ERRORS = u"""
e_cython_parallel.pyx:3:8: cython.parallel.parallel is not a module
e_cython_parallel.pyx:4:0: No such directive: cython.parallel.something
......@@ -41,4 +47,6 @@ e_cython_parallel.pyx:18:19: Invalid schedule argument to prange: 'invalid_sched
e_cython_parallel.pyx:21:5: The parallel section may only be used without the GIL
e_cython_parallel.pyx:27:10: target may not be a Python object as we don't have the GIL
e_cython_parallel.pyx:30:9: Can only iterate over an iteration variable
e_cython_parallel.pyx:33:10: Must be of numeric type, not int *
e_cython_parallel.pyx:36:24: Closely nested 'with parallel:' blocks are disallowed
"""
......@@ -43,30 +43,25 @@ def test_descending_prange():
return sum
def test_nested_prange():
def test_propagation():
"""
Reduction propagation is not (yet) supported.
>>> test_nested_prange()
50
>>> test_propagation()
(9, 9, 9, 9, 450, 450)
"""
cdef int i, j
cdef int sum = 0
for i in prange(5, nogil=True):
for j in prange(5):
sum += i
# The value of sum is undefined here
cdef int i, j, x, y
cdef int sum1 = 0, sum2 = 0
sum = 0
for i in prange(10, nogil=True):
for j in prange(10):
sum1 += i
for i in prange(5, nogil=True):
for j in prange(5):
sum += i
sum += 0
with nogil, cython.parallel.parallel:
for x in prange(10):
with cython.parallel.parallel:
for y in prange(10):
sum2 += y
return sum
return i, j, x, y, sum1, sum2
def test_parallel():
......@@ -225,11 +220,11 @@ def test_parallel_numpy_arrays():
print i
return
x = numpy.zeros(10, dtype=np.int)
x = numpy.zeros(10, dtype=numpy.int)
for i in prange(x.shape[0], nogil=True):
x[i] = i - 5
for i in x:
print x
print i
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment