Skip to content

Commit de69db5

Browse files
authored
Merge pull request #3431 from MetBenjaminWent/force_private_parallel
Add basic means to force promote variables to parallel regions
2 parents 7bf5591 + b2f6998 commit de69db5

4 files changed

Lines changed: 132 additions & 12 deletions

File tree

src/psyclone/psyir/transformations/omp_parallel_trans.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,13 @@
3434
# Authors R. W. Ford, A. R. Porter, S. Siso and N. Nobre, STFC Daresbury Lab
3535
# A. B. G. Chalk STFC Daresbury Lab
3636
# J. Henrichs, Bureau of Meteorology
37-
# Modified I. Kavcic, J. G. Wallwork, O. Brunt and L. Turner, Met Office
38-
# S. Valat, Inria / Laboratoire Jean Kuntzmann
37+
# Modified I. Kavcic, J. G. Wallwork, O. Brunt and L. Turner, B. Went,
38+
# Met Office, S. Valat, Inria / Laboratoire Jean Kuntzmann
3939
# M. Schreiber, Univ. Grenoble Alpes / Inria / Lab. Jean Kuntzmann
4040
# J. Dendy, Met Office
4141
'''This module provides the OMPParallelTrans transformation.'''
4242

43+
from collections.abc import Iterable
4344
from psyclone import psyGen
4445
from psyclone.psyir.nodes import (
4546
ACCDirective,
@@ -48,6 +49,7 @@
4849
OMPParallelDirective,
4950
OMPDirective,
5051
Return,
52+
RegionDirective,
5153
)
5254
from psyclone.psyir.transformations.parallel_region_trans import (
5355
ParallelRegionTrans)
@@ -121,14 +123,31 @@ def validate(self, nodes: list[Node], options=None, **kwargs):
121123
# TODO #2668: Remove options.
122124
super().validate(nodes, options, **kwargs)
123125

124-
def apply(self, nodes: list[Node], options=None, **kwargs):
126+
def apply(
127+
self, nodes: list[Node],
128+
options=None, force_private: Iterable[str] = (),
129+
**kwargs):
125130
'''
126131
Surrounds the provided node list with an OpenMP Parallel region.
127132
128133
:param nodes: list of Nodes to put within parallel region.
134+
:param force_private: list of symbols explicitly requested to
135+
be private.
129136
'''
130137
# TODO #2668: Remove options.
131138
super().apply(nodes, options, **kwargs)
132139

140+
# Privatise the provided variables for the new RegionDirective, if they
141+
# are found within the symbol table of the ancestor Routine.
142+
if force_private:
143+
new_region_directive = nodes[0].ancestor(RegionDirective)
144+
if new_region_directive:
145+
region_set = self._check_symbol_table_vars(
146+
new_region_directive,
147+
force_private)
148+
if region_set:
149+
new_region_directive.explicitly_private_symbols.update(
150+
region_set)
151+
133152

134153
__all__ = ["OMPParallelTrans"]

src/psyclone/psyir/transformations/parallel_region_trans.py

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,24 @@
3434
# Authors R. W. Ford, A. R. Porter, S. Siso and N. Nobre, STFC Daresbury Lab
3535
# A. B. G. Chalk, V. K. Atkinson, STFC Daresbury Lab
3636
# J. Henrichs, Bureau of Meteorology
37-
# Modified I. Kavcic, J. G. Wallwork, O. Brunt and L. Turner, Met Office
38-
# S. Valat, Inria / Laboratoire Jean Kuntzmann
37+
# Modified I. Kavcic, J. G. Wallwork, O. Brunt and L. Turner, B. Went,
38+
# Met Office, S. Valat, Inria / Laboratoire Jean Kuntzmann
3939
# M. Schreiber, Univ. Grenoble Alpes / Inria / Lab. Jean Kuntzmann
4040
# J. Dendy, Met Office
4141

4242
'''
4343
This module provides the implementation of ParallelRegionTrans
4444
4545
'''
46-
46+
import logging
47+
from collections.abc import Iterable
4748
from abc import ABC, abstractmethod
4849
from psyclone.psyir.transformations.transformation_error import (
4950
TransformationError)
5051
from psyclone import psyGen
5152
from psyclone.psyir.transformations.region_trans import RegionTrans
52-
from psyclone.psyir.nodes import CodeBlock, Node, Return
53+
from psyclone.psyir.nodes import CodeBlock, Node, Return, RegionDirective
54+
from psyclone.psyir.symbols import DataSymbol
5355
from psyclone.utils import transformation_documentation_wrapper
5456

5557

@@ -76,6 +78,35 @@ def __str__(self) -> str:
7678
7779
'''
7880

81+
def _check_symbol_table_vars(
82+
self, region_node: RegionDirective,
83+
force_private: Iterable[str] = ()) -> set[DataSymbol]:
84+
'''
85+
Check that the symbol table of the provided region node contains the
86+
variable variables in the provided list. Return a set of DataSymbols.
87+
88+
This is intended to be used as part of privatising the variables
89+
contained in the list for the provided region in the child classes.
90+
'''
91+
explicitly_private_symbols = set()
92+
93+
for symbol_name in force_private:
94+
sym = None
95+
try:
96+
sym = region_node.scope.symbol_table.lookup(
97+
symbol_name.lower())
98+
except KeyError as err:
99+
# This is not an error, but we will log the missed string
100+
logger = logging.getLogger(__name__)
101+
logger.warning(
102+
f"Error: {err} This has been provided with the "
103+
f"'{symbol_name}' in the 'force_private' option, "
104+
"but there is no such symbol in this scope.")
105+
if sym:
106+
explicitly_private_symbols.add(sym)
107+
108+
return explicitly_private_symbols
109+
79110
def validate(self, nodes: list[Node], options=None, **kwargs):
80111
# pylint: disable=arguments-renamed
81112
'''

src/psyclone/tests/psyir/transformations/maximal_region_trans_test.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
# POSSIBILITY OF SUCH DAMAGE.
3333
# -----------------------------------------------------------------------------
3434
# Authors A. B. G. Chalk, STFC Daresbury Lab
35+
# Modified B. Went, Met Office
3536

3637
'''This module contains the tests for the MaximalRegionTrans.'''
3738

@@ -42,12 +43,14 @@
4243
Assignment,
4344
IfBlock,
4445
Routine,
46+
Loop,
4547
OMPParallelDirective,
4648
)
4749
from psyclone.psyir.transformations import (
4850
MaximalRegionTrans,
4951
TransformationError,
50-
OMPParallelTrans
52+
OMPParallelTrans,
53+
OMPLoopTrans,
5154
)
5255

5356

@@ -345,3 +348,41 @@ class OneParTrans(MaximalRegionTrans):
345348
assert isinstance(routine.children[0], OMPParallelDirective)
346349
assert isinstance(routine.children[1], Assignment)
347350
assert isinstance(routine.children[2], OMPParallelDirective)
351+
352+
353+
def test_apply_force_private(fortran_reader):
354+
'''Test the apply function of MaxParallelRegionTrans
355+
with force privates.'''
356+
code = """subroutine x
357+
integer :: i, ii, k, l, block
358+
integer :: array_l(8)
359+
block = 2
360+
do ii = 1, 4
361+
do k = 4, 1, -1
362+
l = 0
363+
do i = ii, min(ii+block -1, 4)
364+
l = l + 1
365+
array_l(l) = 1 + 2
366+
end do
367+
end do
368+
end do
369+
end subroutine x
370+
"""
371+
psyir = fortran_reader.psyir_from_source(code)
372+
# Apply loop_trans to all the loops possible.
373+
ltrans = OMPLoopTrans(omp_schedule="static")
374+
ltrans.apply(
375+
psyir.walk(Loop)[0],
376+
ignore_dependencies_for=["array_l"],
377+
nowait=True)
378+
# Apply maximum transformation to code
379+
mtrans = MaxParTrans()
380+
routine = psyir.walk(Routine)
381+
# Note, i, ii, k, l seem to be set as first private
382+
mtrans.apply(routine, force_private=["i", "ii", "k", "l", "array_l"])
383+
# assertions
384+
assert len(psyir.walk(OMPParallelDirective)) == 1
385+
nodes = psyir.walk(Routine)[0].children[:]
386+
assert isinstance(nodes[0], OMPParallelDirective) is True
387+
pdir = nodes[0]
388+
assert len(pdir.explicitly_private_symbols) == 5

src/psyclone/tests/psyir/transformations/parallel_region_trans_test.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
# Authors R. W. Ford, A. R. Porter, S. Siso and N. Nobre, STFC Daresbury Lab
3535
# A. B. G. Chalk, V. K. Atkinson, STFC Daresbury Lab
3636
# J. Henrichs, Bureau of Meteorology
37-
# Modified I. Kavcic, J. G. Wallwork, O. Brunt and L. Turner, Met Office
38-
# S. Valat, Inria / Laboratoire Jean Kuntzmann
37+
# Modified I. Kavcic, J. G. Wallwork, O. Brunt and L. Turner, B. Went,
38+
# Met Office, S. Valat, Inria / Laboratoire Jean Kuntzmann
3939
# M. Schreiber, Univ. Grenoble Alpes / Inria / Lab. Jean Kuntzmann
4040
# J. Dendy, Met Office
4141

@@ -44,11 +44,11 @@
4444
4545
'''
4646

47+
import logging
4748
import pytest
4849
from psyclone.psyir.transformations.transformation_error import (
4950
TransformationError)
50-
from psyclone.psyir.nodes import CodeBlock
51-
from psyclone.psyir.nodes import (Literal, Loop)
51+
from psyclone.psyir.nodes import (CodeBlock, Literal, Loop)
5252
from psyclone.psyir.transformations import OMPParallelTrans
5353
from psyclone.psyir.symbols import DataSymbol, ScalarType
5454

@@ -69,3 +69,32 @@ def test_parallelregion_refuse_codeblock():
6969
otrans.validate([parent])
7070
assert ("Nodes of type 'CodeBlock' cannot be enclosed by a "
7171
"OMPParallelTrans transformation" in str(err.value))
72+
73+
74+
def test_parallelregion_check_symtab_var(fortran_reader, caplog):
75+
'''
76+
Check ParallelRegionTrans._check_symbol_table_vars try and except,
77+
if the logging message produces a warning when a variable is not
78+
in the routine scope.We use OMPParallelTrans as ParallelRegionTrans
79+
is abstract.
80+
'''
81+
otrans = OMPParallelTrans()
82+
code = """subroutine test
83+
integer :: i
84+
do i = 1, 100
85+
86+
end do
87+
end subroutine"""
88+
psyir = fortran_reader.psyir_from_source(code)
89+
otrans.apply(psyir.children[0].children[0])
90+
parallel = psyir.children[0].children[0]
91+
caplog.clear()
92+
with caplog.at_level(logging.WARNING,
93+
logger="psyclone.psyir.transformations"):
94+
otrans._check_symbol_table_vars(parallel, ("j"))
95+
long_string = (
96+
"Error: \"Could not find 'j' in the Symbol Table.\" This has been "
97+
"provided with the 'j' in the 'force_private' option, "
98+
"but there is no such symbol in this scope."
99+
)
100+
assert long_string in caplog.text

0 commit comments

Comments
 (0)