Reference Guide  2.5.0
psyclone.psyir.transformations.psy_data_trans.PSyDataTrans Class Reference
Inheritance diagram for psyclone.psyir.transformations.psy_data_trans.PSyDataTrans:
Collaboration diagram for psyclone.psyir.transformations.psy_data_trans.PSyDataTrans:

Public Member Functions

def __init__ (self, node_class=PSyDataNode)
 
def __str__ (self)
 
def name (self)
 
def get_default_options (self)
 
def merge_in_default_options (self, options)
 
def get_unique_region_name (self, nodes, options)
 
def validate (self, nodes, options=None)
 
def apply (self, nodes, options=None)
 
- Public Member Functions inherited from psyclone.psyir.transformations.region_trans.RegionTrans
def get_node_list (self, nodes)
 

Static Public Attributes

tuple excluded_node_types = (Return,)
 
- Static Public Attributes inherited from psyclone.psyir.transformations.region_trans.RegionTrans
tuple excluded_node_types = ()
 

Detailed Description

 Create a PSyData region around a list of statements. For
example:

>>> from psyclone.parse.algorithm import parse
>>> from psyclone.parse.utils import ParseError
>>> from psyclone.psyGen import PSyFactory
>>> api = "gocean1.0"
>>> ast, invoke_info = parse(SOURCE_FILE, api=api)
>>> psy = PSyFactory(api).create(invoke_info)
>>>
>>> from psyclone.psyir.transformations import PSyDataTrans
>>> data_trans = PSyDataTrans()
>>>
>>> schedule = psy.invokes.get('invoke_0').schedule
>>> # Uncomment the following line to see a text view of the schedule
>>> # print(schedule.view())
>>>
>>> # Enclose all children within a single PSyData region
>>> data_trans.apply(schedule.children)
>>> # Uncomment the following line to see a text view of the schedule
>>> # print(schedule.view())
>>> # Or to use custom region name:
>>> data_trans.apply(schedule.children,
...                  {"region_name": ("module","region")})

:param node_class: The Node class of which an instance will be inserted \
    into the tree (defaults to PSyDataNode).
:type node_class: :py:class:`psyclone.psyir.nodes.ExtractNode`

Definition at line 50 of file psy_data_trans.py.

Member Function Documentation

◆ apply()

def psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.apply (   self,
  nodes,
  options = None 
)
Apply this transformation to a subset of the nodes within a
schedule - i.e. enclose the specified Nodes in the
schedule within a single PSyData region.

:param nodes: can be a single node or a list of nodes.
:type nodes: :py:obj:`psyclone.psyir.nodes.Node` or list of \
             :py:obj:`psyclone.psyir.nodes.Node`
:param options: a dictionary with options for transformations.
:type options: Optional[Dict[str, Any]]
:param str options["prefix"]: a prefix to use for the PSyData module \
    name (``PREFIX_psy_data_mod``) and the PSyDataType \
    (``PREFIX_PSYDATATYPE``) - a "_" will be added automatically. \
    It defaults to "".
:param (str,str) options["region_name"]: an optional name to \
    use for this PSyData area, provided as a 2-tuple containing a \
    location name followed by a local name. The pair of strings \
    should uniquely identify a region unless aggregate information \
    is required (and is supported by the runtime library).

Reimplemented from psyclone.psyGen.Transformation.

Definition at line 301 of file psy_data_trans.py.

301  def apply(self, nodes, options=None):
302  # pylint: disable=arguments-renamed
303  '''Apply this transformation to a subset of the nodes within a
304  schedule - i.e. enclose the specified Nodes in the
305  schedule within a single PSyData region.
306 
307  :param nodes: can be a single node or a list of nodes.
308  :type nodes: :py:obj:`psyclone.psyir.nodes.Node` or list of \
309  :py:obj:`psyclone.psyir.nodes.Node`
310  :param options: a dictionary with options for transformations.
311  :type options: Optional[Dict[str, Any]]
312  :param str options["prefix"]: a prefix to use for the PSyData module \
313  name (``PREFIX_psy_data_mod``) and the PSyDataType \
314  (``PREFIX_PSYDATATYPE``) - a "_" will be added automatically. \
315  It defaults to "".
316  :param (str,str) options["region_name"]: an optional name to \
317  use for this PSyData area, provided as a 2-tuple containing a \
318  location name followed by a local name. The pair of strings \
319  should uniquely identify a region unless aggregate information \
320  is required (and is supported by the runtime library).
321 
322  '''
323  node_list = self.get_node_list(nodes)
324 
325  # Add any transformation-specific settings that are required:
326  my_options = self.merge_in_default_options(options)
327  # Perform validation checks
328  self.validate(node_list, my_options)
329 
330  # Get useful references
331  parent = node_list[0].parent
332  position = node_list[0].position
333 
334  # We always use the Routine symbol table
335  table = node_list[0].ancestor(Routine).symbol_table
336 
337  # Create an instance of the required class that implements
338  # the code extraction using the PSyData API, e.g. a
339  # ExtractNode. We pass the user-specified options to the
340  # create() method. An example use case for this is the
341  # 'create_driver' flag, where the calling program can control if
342  # a stand-alone driver program should be created or not (when
343  # performing kernel extraction).
344  for node in node_list:
345  node.detach()
346 
347  psy_data_node = self._node_class.create(
348  node_list, symbol_table=table, options=my_options)
349  parent.addchild(psy_data_node, position)
350 
351 
352 # =============================================================================
353 # For AutoAPI documentation generation

References psyclone.psyir.transformations.psy_data_trans.PSyDataTrans._node_class, psyclone.psyir.transformations.region_trans.RegionTrans.get_node_list(), psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.merge_in_default_options(), psyclone.domain.lfric.kernel.lfric_kernel_metadata.LFRicKernelMetadata.validate(), psyclone.transformations.MoveTrans.validate(), psyclone.transformations.Dynamo0p3AsyncHaloExchangeTrans.validate(), psyclone.domain.common.transformations.alg_invoke_2_psy_call_trans.AlgInvoke2PSyCallTrans.validate(), psyclone.domain.common.transformations.alg_trans.AlgTrans.validate(), psyclone.domain.common.transformations.kernel_module_inline_trans.KernelModuleInlineTrans.validate(), psyclone.domain.common.transformations.raise_psyir_2_alg_trans.RaisePSyIR2AlgTrans.validate(), psyclone.domain.gocean.transformations.gocean_const_loop_bounds_trans.GOConstLoopBoundsTrans.validate(), psyclone.domain.gocean.transformations.gocean_move_iteration_boundaries_inside_kernel_trans.GOMoveIterationBoundariesInsideKernelTrans.validate(), psyclone.domain.gocean.transformations.gocean_opencl_trans.GOOpenCLTrans.validate(), psyclone.domain.gocean.transformations.raise_psyir_2_gocean_kern_trans.RaisePSyIR2GOceanKernTrans.validate(), psyclone.domain.lfric.transformations.lfric_alg_invoke_2_psy_call_trans.LFRicAlgInvoke2PSyCallTrans.validate(), psyclone.domain.lfric.transformations.raise_psyir_2_lfric_kern_trans.RaisePSyIR2LFRicKernTrans.validate(), psyclone.domain.nemo.transformations.create_nemo_invoke_schedule_trans.CreateNemoInvokeScheduleTrans.validate(), psyclone.domain.nemo.transformations.create_nemo_psy_trans.CreateNemoPSyTrans.validate(), psyclone.domain.nemo.transformations.nemo_allarrayrange2loop_trans.NemoAllArrayRange2LoopTrans.validate(), psyclone.domain.nemo.transformations.nemo_arrayrange2loop_trans.NemoArrayRange2LoopTrans.validate(), psyclone.domain.nemo.transformations.nemo_outerarrayrange2loop_trans.NemoOuterArrayRange2LoopTrans.validate(), psyclone.psyad.transformations.assignment_trans.AssignmentTrans.validate(), psyclone.psyGen.Transformation.validate(), psyclone.psyir.transformations.acc_update_trans.ACCUpdateTrans.validate(), psyclone.psyir.transformations.allarrayaccess2loop_trans.AllArrayAccess2LoopTrans.validate(), psyclone.psyir.transformations.arrayaccess2loop_trans.ArrayAccess2LoopTrans.validate(), psyclone.psyir.transformations.arrayrange2loop_trans.ArrayRange2LoopTrans.validate(), psyclone.psyir.transformations.chunk_loop_trans.ChunkLoopTrans.validate(), psyclone.psyir.transformations.fold_conditional_return_expressions_trans.FoldConditionalReturnExpressionsTrans.validate(), psyclone.psyir.transformations.hoist_local_arrays_trans.HoistLocalArraysTrans.validate(), psyclone.psyir.transformations.hoist_loop_bound_expr_trans.HoistLoopBoundExprTrans.validate(), psyclone.psyir.transformations.hoist_trans.HoistTrans.validate(), psyclone.psyir.transformations.inline_trans.InlineTrans.validate(), psyclone.psyir.transformations.intrinsics.array_reduction_base_trans.ArrayReductionBaseTrans.validate(), psyclone.psyir.transformations.intrinsics.dotproduct2code_trans.DotProduct2CodeTrans.validate(), psyclone.psyir.transformations.intrinsics.intrinsic2code_trans.Intrinsic2CodeTrans.validate(), psyclone.psyir.transformations.intrinsics.matmul2code_trans.Matmul2CodeTrans.validate(), psyclone.psyir.transformations.loop_swap_trans.LoopSwapTrans.validate(), psyclone.psyir.transformations.loop_tiling_2d_trans.LoopTiling2DTrans.validate(), psyclone.psyir.transformations.loop_trans.LoopTrans.validate(), psyclone.psyir.transformations.omp_task_trans.OMPTaskTrans.validate(), psyclone.psyir.transformations.omp_taskwait_trans.OMPTaskwaitTrans.validate(), psyclone.psyir.transformations.parallel_loop_trans.ParallelLoopTrans.validate(), psyclone.psyir.transformations.reference2arrayrange_trans.Reference2ArrayRangeTrans.validate(), psyclone.psyir.transformations.replace_induction_variables_trans.ReplaceInductionVariablesTrans.validate(), psyclone.transformations.OMPDeclareTargetTrans.validate(), psyclone.transformations.DynamoOMPParallelLoopTrans.validate(), psyclone.transformations.Dynamo0p3OMPLoopTrans.validate(), psyclone.transformations.GOceanOMPLoopTrans.validate(), psyclone.transformations.Dynamo0p3RedundantComputationTrans.validate(), psyclone.transformations.Dynamo0p3KernelConstTrans.validate(), psyclone.transformations.ACCRoutineTrans.validate(), psyclone.transformations.KernelImportsToArguments.validate(), psyclone.domain.gocean.transformations.gocean_loop_fuse_trans.GOceanLoopFuseTrans.validate(), psyclone.domain.lfric.transformations.lfric_loop_fuse_trans.LFRicLoopFuseTrans.validate(), psyclone.psyir.transformations.loop_fuse_trans.LoopFuseTrans.validate(), psyclone.domain.gocean.transformations.gocean_extract_trans.GOceanExtractTrans.validate(), psyclone.domain.lfric.transformations.lfric_extract_trans.LFRicExtractTrans.validate(), psyclone.psyir.transformations.extract_trans.ExtractTrans.validate(), psyclone.psyir.transformations.nan_test_trans.NanTestTrans.validate(), psyclone.psyir.transformations.read_only_verify_trans.ReadOnlyVerifyTrans.validate(), psyclone.transformations.ParallelRegionTrans.validate(), psyclone.transformations.OMPParallelTrans.validate(), psyclone.transformations.ACCParallelTrans.validate(), psyclone.transformations.ACCKernelsTrans.validate(), psyclone.transformations.ACCDataTrans.validate(), psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.validate(), psyclone.psyir.transformations.region_trans.RegionTrans.validate(), and psyclone.transformations.ACCEnterDataTrans.validate().

Here is the call graph for this function:

◆ get_default_options()

def psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.get_default_options (   self)
Returns a new dictionary with additional options, specific to the
transformation, that will be added to the user option. Any values
specified by the user will take precedence.

:returns: a dictionary with additional options.
:rtype: Dict[str, Any]

Reimplemented in psyclone.psyir.transformations.read_only_verify_trans.ReadOnlyVerifyTrans, and psyclone.psyir.transformations.extract_trans.ExtractTrans.

Definition at line 115 of file psy_data_trans.py.

115  def get_default_options(self):
116  '''Returns a new dictionary with additional options, specific to the
117  transformation, that will be added to the user option. Any values
118  specified by the user will take precedence.
119 
120  :returns: a dictionary with additional options.
121  :rtype: Dict[str, Any]
122  '''
123 
124  return {}
125 
Here is the caller graph for this function:

◆ get_unique_region_name()

def psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.get_unique_region_name (   self,
  nodes,
  options 
)
This function returns the region and module name. If they are
specified in the user options, these names will just be returned (it
is then up to the user to guarantee uniqueness). Otherwise a name
based on the module and invoke will be created using indices to
make sure the name is unique.

:param nodes: a list of nodes.
:type nodes: list of :py:obj:`psyclone.psyir.nodes.Node`
:param options: a dictionary with options for transformations.
:type options: Dict[str, Any]
:param (str,str) options["region_name"]: an optional name to \
    use for this PSyData area, provided as a 2-tuple containing a \
    location name followed by a local name. The pair of strings \
    should uniquely identify a region unless aggregate information \
    is required (and is supported by the runtime library).

Definition at line 148 of file psy_data_trans.py.

148  def get_unique_region_name(self, nodes, options):
149  '''This function returns the region and module name. If they are
150  specified in the user options, these names will just be returned (it
151  is then up to the user to guarantee uniqueness). Otherwise a name
152  based on the module and invoke will be created using indices to
153  make sure the name is unique.
154 
155  :param nodes: a list of nodes.
156  :type nodes: list of :py:obj:`psyclone.psyir.nodes.Node`
157  :param options: a dictionary with options for transformations.
158  :type options: Dict[str, Any]
159  :param (str,str) options["region_name"]: an optional name to \
160  use for this PSyData area, provided as a 2-tuple containing a \
161  location name followed by a local name. The pair of strings \
162  should uniquely identify a region unless aggregate information \
163  is required (and is supported by the runtime library).
164 
165  '''
166  # We don't use a static method here since it might be useful to
167  # overwrite this functions in derived classes
168  name = options.get("region_name", None)
169  if name:
170  # pylint: disable=too-many-boolean-expressions
171  if not isinstance(name, tuple) or not len(name) == 2 or \
172  not name[0] or not isinstance(name[0], str) or \
173  not name[1] or not isinstance(name[1], str):
174  raise InternalError(
175  "Error in PSyDataTrans. The name must be a "
176  "tuple containing two non-empty strings.")
177  # pylint: enable=too-many-boolean-expressions
178  # Valid PSyData names have been provided by the user.
179  return name
180 
181  invoke = nodes[0].ancestor(InvokeSchedule).invoke
182  module_name = invoke.invokes.psy.name
183 
184  # Use the invoke name as a starting point.
185  region_name = invoke.name
186  kerns = []
187  for node in nodes:
188  kerns.extend(node.walk(Kern))
189 
190  if len(kerns) == 1:
191  # This PSyData region only has one kernel within it,
192  # so append the kernel name.
193  region_name += f":{kerns[0].name}"
194 
195  # Add a region index to ensure uniqueness when there are
196  # multiple regions in an invoke.
197  key = module_name + "|" + region_name
198  idx = PSyDataTrans._used_kernel_names.get(key, 0)
199  PSyDataTrans._used_kernel_names[key] = idx + 1
200  region_name += f":r{idx}"
201  return (module_name, region_name)
202 
Here is the caller graph for this function:

◆ merge_in_default_options()

def psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.merge_in_default_options (   self,
  options 
)
This function returns a new dictionary which contains the default
options for this transformation plus al user-specified options.
Any user-specified option will take precedence over the default
values.

:param options: a dictionary with options for transformations.
:type options: Dict[str, Any]
:returns: a new dictionary which merges the default options with \
    the user-specified options.
:rtype: Dict[str:Any]

Definition at line 127 of file psy_data_trans.py.

127  def merge_in_default_options(self, options):
128  '''This function returns a new dictionary which contains the default
129  options for this transformation plus al user-specified options.
130  Any user-specified option will take precedence over the default
131  values.
132 
133  :param options: a dictionary with options for transformations.
134  :type options: Dict[str, Any]
135  :returns: a new dictionary which merges the default options with \
136  the user-specified options.
137  :rtype: Dict[str:Any]
138 
139  '''
140  new_options = self.get_default_options()
141  if options:
142  # Update will overwrite any existing setting with the ones
143  # specified by the user:
144  new_options.update(options)
145  return new_options
146 

References psyclone.psyir.transformations.extract_trans.ExtractTrans.get_default_options(), psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.get_default_options(), and psyclone.psyir.transformations.read_only_verify_trans.ReadOnlyVerifyTrans.get_default_options().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ name()

def psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.name (   self)
This function returns the name of the transformation.
It uses the Python 2/3 compatible way of returning the
class name as a string, which means that the same function can
be used for all derived classes.

:returns: the name of this transformation as a string.
:rtype: str

Reimplemented from psyclone.psyGen.Transformation.

Definition at line 102 of file psy_data_trans.py.

102  def name(self):
103  '''This function returns the name of the transformation.
104  It uses the Python 2/3 compatible way of returning the
105  class name as a string, which means that the same function can
106  be used for all derived classes.
107 
108  :returns: the name of this transformation as a string.
109  :rtype: str
110  '''
111 
112  return self.__class__.__name__
113 

References psyclone.psyir.symbols.symbol.Symbol.__class__.

Here is the caller graph for this function:

◆ validate()

def psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.validate (   self,
  nodes,
  options = None 
)
Checks that the supplied list of nodes is valid, that the location
for this node is valid (not between a loop-directive and its loop),
that there aren't any name clashes with symbols that must be
imported from the appropriate PSyData library and finally, calls the
validate method of the base class.

:param nodes: a node or list of nodes to be instrumented with \
    PSyData API calls.
:type nodes: (list of) :py:class:`psyclone.psyir.nodes.Loop`

:param options: a dictionary with options for transformations.
:type options: Optional[Dict[str, Any]]
:param str options["prefix"]: a prefix to use for the PSyData module \
    name (``PREFIX_psy_data_mod``) and the PSyDataType \
    (``PREFIX_PSYDATATYPE``) - a "_" will be added automatically. \
    It defaults to "".
:param (str,str) options["region_name"]: an optional name to \
    use for this PSyData area, provided as a 2-tuple containing a \
    location name followed by a local name. The pair of strings \
    should uniquely identify a region unless aggregate information \
    is required (and is supported by the runtime library).

:raises TransformationError: if the supplied list of nodes is empty.
:raises TransformationError: if the PSyData node is inserted \
    between an OpenMP/ACC directive and the loop(s) to which it \
    applies.
:raises TransformationError: if the 'prefix' or 'region_name' options \
    are not valid.
:raises TransformationError: if there will be a name clash between \
    any existing symbols and those that must be imported from the \
    appropriate PSyData library.

Reimplemented from psyclone.psyir.transformations.region_trans.RegionTrans.

Reimplemented in psyclone.psyir.transformations.read_only_verify_trans.ReadOnlyVerifyTrans, and psyclone.psyir.transformations.extract_trans.ExtractTrans.

Definition at line 204 of file psy_data_trans.py.

204  def validate(self, nodes, options=None):
205  '''
206  Checks that the supplied list of nodes is valid, that the location
207  for this node is valid (not between a loop-directive and its loop),
208  that there aren't any name clashes with symbols that must be
209  imported from the appropriate PSyData library and finally, calls the
210  validate method of the base class.
211 
212  :param nodes: a node or list of nodes to be instrumented with \
213  PSyData API calls.
214  :type nodes: (list of) :py:class:`psyclone.psyir.nodes.Loop`
215 
216  :param options: a dictionary with options for transformations.
217  :type options: Optional[Dict[str, Any]]
218  :param str options["prefix"]: a prefix to use for the PSyData module \
219  name (``PREFIX_psy_data_mod``) and the PSyDataType \
220  (``PREFIX_PSYDATATYPE``) - a "_" will be added automatically. \
221  It defaults to "".
222  :param (str,str) options["region_name"]: an optional name to \
223  use for this PSyData area, provided as a 2-tuple containing a \
224  location name followed by a local name. The pair of strings \
225  should uniquely identify a region unless aggregate information \
226  is required (and is supported by the runtime library).
227 
228  :raises TransformationError: if the supplied list of nodes is empty.
229  :raises TransformationError: if the PSyData node is inserted \
230  between an OpenMP/ACC directive and the loop(s) to which it \
231  applies.
232  :raises TransformationError: if the 'prefix' or 'region_name' options \
233  are not valid.
234  :raises TransformationError: if there will be a name clash between \
235  any existing symbols and those that must be imported from the \
236  appropriate PSyData library.
237 
238  '''
239  # pylint: disable=too-many-branches
240  node_list = self.get_node_list(nodes)
241 
242  if not node_list:
243  raise TransformationError("Cannot apply transformation to an "
244  "empty list of nodes.")
245 
246  node_parent = node_list[0].parent
247  if isinstance(node_parent, Schedule) and \
248  isinstance(node_parent.parent, (OMPDoDirective, ACCLoopDirective)):
249  raise TransformationError("A PSyData node cannot be inserted "
250  "between an OpenMP/ACC directive and "
251  "the loop(s) to which it applies!")
252 
253  if node_list[0].ancestor(ACCDirective):
254  raise TransformationError("A PSyData node cannot be inserted "
255  "inside an OpenACC region.")
256 
257  my_options = self.merge_in_default_options(options)
258  if "region_name" in my_options:
259  name = my_options["region_name"]
260  # pylint: disable=too-many-boolean-expressions
261  if not isinstance(name, tuple) or not len(name) == 2 or \
262  not name[0] or not isinstance(name[0], str) or \
263  not name[1] or not isinstance(name[1], str):
264  raise TransformationError(
265  f"Error in {self.name}. User-supplied region name "
266  f"must be a tuple containing two non-empty strings.")
267  # pylint: enable=too-many-boolean-expressions
268  prefix = my_options.get("prefix", None)
269  if "prefix" in my_options:
270  prefix = my_options.get("prefix", None)
271  if prefix not in Config.get().valid_psy_data_prefixes:
272  raise TransformationError(
273  f"Error in 'prefix' parameter: found '{prefix}', while"
274  f" one of {Config.get().valid_psy_data_prefixes} was "
275  f"expected as defined in {Config.get().filename}")
276 
277  # We have to create an instance of the node that will be inserted in
278  # order to find out what module name it will use.
279  pdata_node = self._node_class(options=my_options)
280  table = node_list[0].scope.symbol_table
281  for name in ([sym.name for sym in pdata_node.imported_symbols] +
282  [pdata_node.fortran_module]):
283  try:
284  _ = table.lookup_with_tag(name)
285  except KeyError as err:
286  # The tag doesn't exist which means that we haven't already
287  # added this symbol as part of a PSyData transformation. Check
288  # for any clashes with existing symbols.
289  try:
290  _ = table.lookup(name)
291  raise TransformationError(
292  f"Cannot add PSyData calls because there is already a "
293  f"symbol named '{name}' which clashes with one of "
294  f"those used by the PSyclone PSyData API. ") from err
295  except KeyError:
296  pass
297 
298  super().validate(node_list, my_options)
299 

References psyclone.psyir.transformations.psy_data_trans.PSyDataTrans._node_class, psyclone.psyir.transformations.region_trans.RegionTrans.get_node_list(), and psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.merge_in_default_options().

Here is the call graph for this function:
Here is the caller graph for this function:

The documentation for this class was generated from the following file: