Reference Guide  2.5.0
psyclone.psyGen.CodedKern Class Reference
Inheritance diagram for psyclone.psyGen.CodedKern:
Collaboration diagram for psyclone.psyGen.CodedKern:

Public Member Functions

def __init__ (self, KernelArguments, call, parent=None, check=True)
 
def get_kernel_schedule (self)
 
def opencl_options (self)
 
def set_opencl_options (self, options)
 
def __str__ (self)
 
def module_name (self)
 
def dag_name (self)
 
def module_inline (self)
 
def module_inline (self, value)
 
def node_str (self, colour=True)
 
def lower_to_language_level (self)
 
def incremented_arg (self)
 
def ast (self)
 
def rename_and_write (self)
 
def modified (self)
 
def modified (self, value)
 
- Public Member Functions inherited from psyclone.psyGen.Kern
def __init__ (self, parent, call, name, ArgumentsClass, check=True)
 
def args (self)
 
def reference_accesses (self, var_accesses)
 
def is_reduction (self)
 
def reduction_arg (self)
 
def reprod_reduction (self)
 
def local_reduction_name (self)
 
def zero_reduction_variable (self, parent, position=None)
 
def reduction_sum_loop (self, parent)
 
def arg_descriptors (self)
 
def arg_descriptors (self, obj)
 
def arguments (self)
 
def name (self)
 
def name (self, value)
 
def is_coloured (self)
 
def iterates_over (self)
 
def local_vars (self)
 
def gen_code (self, parent)
 

Public Attributes

 arg_descriptors
 
 modified
 
 name
 

Detailed Description

Class representing a call to a PSyclone Kernel with a user-provided
implementation. The kernel may or may not be in-lined.

:param type KernelArguments: the API-specific sub-class of \
                             :py:class:`psyclone.psyGen.Arguments` to \
                             create.
:param call: Details of the call to this kernel in the Algorithm layer.
:type call: :py:class:`psyclone.parse.algorithm.KernelCall`.
:param parent: the parent of this Node (kernel call) in the Schedule.
:type parent: sub-class of :py:class:`psyclone.psyir.nodes.Node`.
:param bool check: whether to check for consistency between the \
    kernel metadata and the algorithm layer. Defaults to True.

Definition at line 1337 of file psyGen.py.

Member Function Documentation

◆ ast()

def psyclone.psyGen.CodedKern.ast (   self)
Generate and return the fparser2 AST of the kernel source.

:returns: fparser2 AST of the Fortran file containing this kernel.
:rtype: :py:class:`fparser.two.Fortran2003.Program`

Definition at line 1569 of file psyGen.py.

1569  def ast(self):
1570  '''
1571  Generate and return the fparser2 AST of the kernel source.
1572 
1573  :returns: fparser2 AST of the Fortran file containing this kernel.
1574  :rtype: :py:class:`fparser.two.Fortran2003.Program`
1575  '''
1576  from fparser.common.readfortran import FortranStringReader
1577  from fparser.two import parser
1578  # If we've already got the AST then just return it
1579  if self._fp2_ast:
1580  return self._fp2_ast
1581  # Use the fparser1 AST to generate Fortran source
1582  fortran = self._module_code.tofortran()
1583  # Create an fparser2 Fortran2008 parser
1584  my_parser = parser.ParserFactory().create(std="f2008")
1585  # Parse that Fortran using our parser
1586  reader = FortranStringReader(fortran)
1587  self._fp2_ast = my_parser(reader)
1588  return self._fp2_ast
1589 

References psyclone.psyGen.CodedKern._fp2_ast, and psyclone.psyGen.CodedKern._module_code.

Here is the caller graph for this function:

◆ dag_name()

def psyclone.psyGen.CodedKern.dag_name (   self)
:returns: the name to use in the DAG for this node.
:rtype: str

Definition at line 1445 of file psyGen.py.

1445  def dag_name(self):
1446  '''
1447  :returns: the name to use in the DAG for this node.
1448  :rtype: str
1449  '''
1450  _, position = self._find_position(self.ancestor(Routine))
1451  return f"kernel_{self.name}_{position}"
1452 

References psyclone.psyir.nodes.node.Node._find_position(), and psyclone.psyir.nodes.node.Node.ancestor().

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

◆ get_kernel_schedule()

def psyclone.psyGen.CodedKern.get_kernel_schedule (   self)
Returns a PSyIR Schedule representing the kernel code. The Schedule
is just generated on first invocation, this allows us to retain
transformations that may subsequently be applied to the Schedule.

:returns: Schedule representing the kernel code.
:rtype: :py:class:`psyclone.psyir.nodes.KernelSchedule`

Reimplemented in psyclone.gocean1p0.GOKern, and psyclone.domain.lfric.lfric_kern.LFRicKern.

Definition at line 1377 of file psyGen.py.

1377  def get_kernel_schedule(self):
1378  '''
1379  Returns a PSyIR Schedule representing the kernel code. The Schedule
1380  is just generated on first invocation, this allows us to retain
1381  transformations that may subsequently be applied to the Schedule.
1382 
1383  :returns: Schedule representing the kernel code.
1384  :rtype: :py:class:`psyclone.psyir.nodes.KernelSchedule`
1385  '''
1386  from psyclone.psyir.frontend.fparser2 import Fparser2Reader
1387  if self._kern_schedule is None:
1388  astp = Fparser2Reader()
1389  self._kern_schedule = astp.generate_schedule(self.name, self.ast)
1390  # TODO: Validate kernel with metadata (issue #288).
1391  return self._kern_schedule
1392 

References psyclone.domain.lfric.lfric_kern.LFRicKern._kern_schedule, psyclone.gocean1p0.GOKern._kern_schedule, psyclone.psyGen.CodedKern._kern_schedule, psyclone.parse.kernel.KernelProcedure.ast(), psyclone.psyGen.CodedKern.ast(), psyclone.psyir.nodes.codeblock.CodeBlock.ast, psyclone.psyir.nodes.node.Node.ast(), psyclone.domain.gocean.kernel.psyir.GOceanKernelMetadata.name, psyclone.domain.gocean.kernel.psyir.GOceanKernelMetadata.GridArg.name, psyclone.domain.gocean.transformations.gocean_const_loop_bounds_trans.GOConstLoopBoundsTrans.name(), psyclone.domain.gocean.transformations.gocean_move_iteration_boundaries_inside_kernel_trans.GOMoveIterationBoundariesInsideKernelTrans.name(), psyclone.domain.gocean.transformations.gocean_opencl_trans.GOOpenCLTrans.name(), psyclone.domain.lfric.kernel.lfric_kernel_metadata.LFRicKernelMetadata.name, psyclone.domain.nemo.transformations.create_nemo_invoke_schedule_trans.CreateNemoInvokeScheduleTrans.name(), psyclone.domain.nemo.transformations.create_nemo_psy_trans.CreateNemoPSyTrans.name(), psyclone.domain.nemo.transformations.nemo_allarrayrange2loop_trans.NemoAllArrayRange2LoopTrans.name(), psyclone.domain.nemo.transformations.nemo_arrayrange2loop_trans.NemoArrayRange2LoopTrans.name(), psyclone.domain.nemo.transformations.nemo_outerarrayrange2loop_trans.NemoOuterArrayRange2LoopTrans.name(), psyclone.dynamo0p3.DynamoPSy.name(), psyclone.expression.FunctionVar.name, psyclone.expression.NamedArg.name(), psyclone.gocean1p0.GOKernelGridArgument.name(), psyclone.gocean1p0.GOStencil.name(), psyclone.parse.algorithm.FileInfo.name(), psyclone.parse.algorithm.InvokeCall.name(), psyclone.parse.kernel.KernelProcedure.name(), psyclone.parse.kernel.KernelType.name(), psyclone.parse.module_info.ModuleInfo.name(), psyclone.psyad.transformations.assignment_trans.AssignmentTrans.name(), psyclone.psyGen.PSy.name(), psyclone.psyGen.Invoke.name(), psyclone.psyGen.Kern.name(), psyclone.psyGen.CodedKern.name, psyclone.psyGen.Argument.name(), psyclone.psyGen.Transformation.name(), psyclone.psyGen.DummyTransformation.name(), psyclone.psyir.nodes.container.Container.name, psyclone.psyir.nodes.member.Member.name, psyclone.psyir.nodes.reference.Reference.name(), psyclone.psyir.nodes.routine.Routine.name, psyclone.psyir.symbols.symbol.Symbol.name(), psyclone.psyir.transformations.allarrayaccess2loop_trans.AllArrayAccess2LoopTrans.name(), psyclone.psyir.transformations.arrayrange2loop_trans.ArrayRange2LoopTrans.name(), psyclone.psyir.transformations.fold_conditional_return_expressions_trans.FoldConditionalReturnExpressionsTrans.name(), psyclone.psyir.transformations.loop_trans.LoopTrans.name(), psyclone.psyir.transformations.omp_task_trans.OMPTaskTrans.name(), psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.name(), psyclone.transformations.OMPSingleTrans.name(), psyclone.transformations.OMPMasterTrans.name(), psyclone.transformations.OMPParallelTrans.name(), psyclone.transformations.MoveTrans.name(), psyclone.transformations.Dynamo0p3AsyncHaloExchangeTrans.name(), psyclone.transformations.Dynamo0p3KernelConstTrans.name(), psyclone.transformations.ACCEnterDataTrans.name(), psyclone.transformations.ACCRoutineTrans.name(), psyclone.transformations.ACCKernelsTrans.name(), psyclone.transformations.ACCDataTrans.name(), and psyclone.transformations.KernelImportsToArguments.name().

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

◆ incremented_arg()

def psyclone.psyGen.CodedKern.incremented_arg (   self)
 Returns the argument that has INC access. Raises a
FieldNotFoundError if none is found.

:rtype: str
:raises FieldNotFoundError: if none is found.
:returns: a Fortran argument name.

Definition at line 1551 of file psyGen.py.

1551  def incremented_arg(self):
1552  ''' Returns the argument that has INC access. Raises a
1553  FieldNotFoundError if none is found.
1554 
1555  :rtype: str
1556  :raises FieldNotFoundError: if none is found.
1557  :returns: a Fortran argument name.
1558  '''
1559  for arg in self.arguments.args:
1560  if arg.access == AccessType.INC:
1561  return arg
1562 
1563  raise FieldNotFoundError(f"Kernel {self.name} does not have an "
1564  f"argument with "
1565  f"{AccessType.INC.api_specific_name()} "
1566  f"access")
1567 

References psyclone.psyGen.Kern.arguments(), and psyclone.psyir.nodes.call.Call.arguments().

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

◆ lower_to_language_level()

def psyclone.psyGen.CodedKern.lower_to_language_level (   self)
In-place replacement of CodedKern concept into language level
PSyIR constructs. The CodedKern is implemented as a Call to a
routine with the appropriate arguments.

:returns: the lowered version of this node.
:rtype: :py:class:`psyclone.psyir.node.Node`

Definition at line 1500 of file psyGen.py.

1500  def lower_to_language_level(self):
1501  '''
1502  In-place replacement of CodedKern concept into language level
1503  PSyIR constructs. The CodedKern is implemented as a Call to a
1504  routine with the appropriate arguments.
1505 
1506  :returns: the lowered version of this node.
1507  :rtype: :py:class:`psyclone.psyir.node.Node`
1508 
1509  '''
1510  symtab = self.ancestor(InvokeSchedule).symbol_table
1511 
1512  if not self.module_inline:
1513  # If it is not module inlined then make sure we generate the kernel
1514  # file (and rename it when necessary).
1515  self.rename_and_write()
1516  # Then find or create the imported RoutineSymbol
1517  try:
1518  # Limit scope to this Invoke, since a kernel with the same name
1519  # may have been inlined from another invoke in the same file,
1520  # but we have it here marked as "not module-inlined"
1521  rsymbol = symtab.lookup(self._name, scope_limit=symtab.node)
1522  except KeyError:
1523  csymbol = symtab.find_or_create(
1524  self._module_name,
1525  symbol_type=ContainerSymbol)
1526  rsymbol = symtab.new_symbol(
1527  self._name,
1528  symbol_type=RoutineSymbol,
1529  # And allow shadowing in case it is also inlined with
1530  # the same name by another invoke
1531  shadowing=True,
1532  interface=ImportInterface(csymbol))
1533  else:
1534  # If its inlined, the symbol must exist
1535  try:
1536  rsymbol = self.scope.symbol_table.lookup(self._name)
1537  except KeyError as err:
1538  raise GenerationError(
1539  f"Cannot generate this kernel call to '{self.name}' "
1540  f"because it is marked as module-inlined but no such "
1541  f"subroutine exists in this module.") from err
1542 
1543  # Create Call to the rsymbol with the argument expressions as children
1544  # of the new node
1545  call_node = Call.create(rsymbol, self.arguments.psyir_expressions())
1546 
1547  # Swap itself with the appropriate Call node
1548  self.replace_with(call_node)
1549  return call_node
1550 

References psyclone.dynamo0p3.DynKernelArgument._module_name, psyclone.parse.algorithm.ParsedCall._module_name, psyclone.parse.algorithm.KernelCall._module_name, psyclone.psyGen.CodedKern._module_name, psyclone.psyGen.Argument._module_name, psyclone.psyir.nodes.psy_data_node.PSyDataNode._module_name, psyclone.domain.common.algorithm.psyir.AlgorithmInvokeCall._name, psyclone.domain.gocean.kernel.psyir.GOceanKernelMetadata._name, psyclone.domain.gocean.kernel.psyir.GOceanKernelMetadata.GridArg._name, psyclone.domain.lfric.kernel.lfric_kernel_metadata.LFRicKernelMetadata._name, psyclone.dynamo0p3.DynFuncDescriptor03._name, psyclone.expression.NamedArg._name, psyclone.gocean1p0.GOKernelGridArgument._name, psyclone.gocean1p0.GOStencil._name, psyclone.nemo.NemoInvoke._name, psyclone.nemo.NemoPSy._name, psyclone.parse.algorithm.FileInfo._name, psyclone.parse.algorithm.InvokeCall._name, psyclone.parse.kernel.KernelProcedure._name, psyclone.parse.kernel.KernelType._name, psyclone.parse.module_info.ModuleInfo._name, psyclone.psyGen.PSy._name, psyclone.psyGen.Invoke._name, psyclone.psyGen.Kern._name, psyclone.psyGen.Argument._name, psyclone.psyir.nodes.container.Container._name, psyclone.psyir.nodes.routine.Routine._name, psyclone.psyir.symbols.symbol.Symbol._name, psyclone.psyir.nodes.node.Node.ancestor(), psyclone.psyGen.Kern.arguments(), psyclone.psyir.nodes.call.Call.arguments(), psyclone.psyGen.CodedKern.module_inline(), psyclone.psyGen.CodedKern.rename_and_write(), psyclone.psyir.nodes.node.Node.replace_with(), psyclone.psyir.nodes.node.Node.scope(), and psyclone.psyir.symbols.symbol_table.SymbolTable.scope().

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

◆ modified() [1/2]

def psyclone.psyGen.CodedKern.modified (   self)
:returns: Whether or not this kernel has been modified (transformed).
:rtype: bool

Definition at line 1776 of file psyGen.py.

1776  def modified(self):
1777  '''
1778  :returns: Whether or not this kernel has been modified (transformed).
1779  :rtype: bool
1780  '''
1781  return self._modified
1782 

References psyclone.psyGen.CodedKern._modified.

Here is the caller graph for this function:

◆ modified() [2/2]

def psyclone.psyGen.CodedKern.modified (   self,
  value 
)
Setter for whether or not this kernel has been modified.

:param bool value: True if kernel modified, False otherwise.

Definition at line 1784 of file psyGen.py.

1784  def modified(self, value):
1785  '''
1786  Setter for whether or not this kernel has been modified.
1787 
1788  :param bool value: True if kernel modified, False otherwise.
1789  '''
1790  self._modified = value
1791 
1792 

References psyclone.psyGen.CodedKern._modified.

Here is the caller graph for this function:

◆ module_inline() [1/2]

def psyclone.psyGen.CodedKern.module_inline (   self)
:returns: whether or not this kernel is being module-inlined.
:rtype: bool

Definition at line 1454 of file psyGen.py.

1454  def module_inline(self):
1455  '''
1456  :returns: whether or not this kernel is being module-inlined.
1457  :rtype: bool
1458  '''
1459  return self._module_inline
1460 

References psyclone.psyGen.CodedKern._module_inline.

Here is the caller graph for this function:

◆ module_inline() [2/2]

def psyclone.psyGen.CodedKern.module_inline (   self,
  value 
)
Setter for whether or not to module-inline this kernel.

:param bool value: whether or not to module-inline this kernel.

Definition at line 1462 of file psyGen.py.

1462  def module_inline(self, value):
1463  '''
1464  Setter for whether or not to module-inline this kernel.
1465 
1466  :param bool value: whether or not to module-inline this kernel.
1467  '''
1468  if value is not True:
1469  raise TypeError(
1470  f"The module inline parameter only accepts the type boolean "
1471  f"'True' since module-inlining is irreversible. But found:"
1472  f" '{value}'.")
1473  # Do the same to all kernels in this invoke with the same name.
1474  # This is needed because gen_code/lowering would otherwise add
1475  # an import with the same name and shadow the module-inline routine
1476  # symbol.
1477  # TODO 1823: The transformation could have more control about this by
1478  # giving an option to specify if the module-inline applies to a
1479  # single kernel, the whole invoke or the whole algorithm.
1480  my_schedule = self.ancestor(InvokeSchedule)
1481  for kernel in my_schedule.walk(Kern):
1482  if kernel is self:
1483  self._module_inline = value
1484  elif kernel.name == self.name and kernel.module_inline != value:
1485  kernel.module_inline = value
1486 

References psyclone.psyGen.CodedKern._module_inline, psyclone.psyir.nodes.node.Node.ancestor(), psyclone.psyGen.CodedKern.module_inline(), psyclone.domain.gocean.kernel.psyir.GOceanKernelMetadata.name, psyclone.domain.gocean.kernel.psyir.GOceanKernelMetadata.GridArg.name, psyclone.domain.gocean.transformations.gocean_const_loop_bounds_trans.GOConstLoopBoundsTrans.name(), psyclone.domain.gocean.transformations.gocean_move_iteration_boundaries_inside_kernel_trans.GOMoveIterationBoundariesInsideKernelTrans.name(), psyclone.domain.gocean.transformations.gocean_opencl_trans.GOOpenCLTrans.name(), psyclone.domain.lfric.kernel.lfric_kernel_metadata.LFRicKernelMetadata.name, psyclone.domain.nemo.transformations.create_nemo_invoke_schedule_trans.CreateNemoInvokeScheduleTrans.name(), psyclone.domain.nemo.transformations.create_nemo_psy_trans.CreateNemoPSyTrans.name(), psyclone.domain.nemo.transformations.nemo_allarrayrange2loop_trans.NemoAllArrayRange2LoopTrans.name(), psyclone.domain.nemo.transformations.nemo_arrayrange2loop_trans.NemoArrayRange2LoopTrans.name(), psyclone.domain.nemo.transformations.nemo_outerarrayrange2loop_trans.NemoOuterArrayRange2LoopTrans.name(), psyclone.dynamo0p3.DynamoPSy.name(), psyclone.expression.FunctionVar.name, psyclone.expression.NamedArg.name(), psyclone.gocean1p0.GOKernelGridArgument.name(), psyclone.gocean1p0.GOStencil.name(), psyclone.parse.algorithm.FileInfo.name(), psyclone.parse.algorithm.InvokeCall.name(), psyclone.parse.kernel.KernelProcedure.name(), psyclone.parse.kernel.KernelType.name(), psyclone.parse.module_info.ModuleInfo.name(), psyclone.psyad.transformations.assignment_trans.AssignmentTrans.name(), psyclone.psyGen.PSy.name(), psyclone.psyGen.Invoke.name(), psyclone.psyGen.Kern.name(), psyclone.psyGen.CodedKern.name, psyclone.psyGen.Argument.name(), psyclone.psyGen.Transformation.name(), psyclone.psyGen.DummyTransformation.name(), psyclone.psyir.nodes.container.Container.name, psyclone.psyir.nodes.member.Member.name, psyclone.psyir.nodes.reference.Reference.name(), psyclone.psyir.nodes.routine.Routine.name, psyclone.psyir.symbols.symbol.Symbol.name(), psyclone.psyir.transformations.allarrayaccess2loop_trans.AllArrayAccess2LoopTrans.name(), psyclone.psyir.transformations.arrayrange2loop_trans.ArrayRange2LoopTrans.name(), psyclone.psyir.transformations.fold_conditional_return_expressions_trans.FoldConditionalReturnExpressionsTrans.name(), psyclone.psyir.transformations.loop_trans.LoopTrans.name(), psyclone.psyir.transformations.omp_task_trans.OMPTaskTrans.name(), psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.name(), psyclone.transformations.OMPSingleTrans.name(), psyclone.transformations.OMPMasterTrans.name(), psyclone.transformations.OMPParallelTrans.name(), psyclone.transformations.MoveTrans.name(), psyclone.transformations.Dynamo0p3AsyncHaloExchangeTrans.name(), psyclone.transformations.Dynamo0p3KernelConstTrans.name(), psyclone.transformations.ACCEnterDataTrans.name(), psyclone.transformations.ACCRoutineTrans.name(), psyclone.transformations.ACCKernelsTrans.name(), psyclone.transformations.ACCDataTrans.name(), and psyclone.transformations.KernelImportsToArguments.name().

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

◆ module_name()

def psyclone.psyGen.CodedKern.module_name (   self)
:returns: The name of the Fortran module that contains this kernel
:rtype: string

Definition at line 1437 of file psyGen.py.

1437  def module_name(self):
1438  '''
1439  :returns: The name of the Fortran module that contains this kernel
1440  :rtype: string
1441  '''
1442  return self._module_name
1443 

References psyclone.dynamo0p3.DynKernelArgument._module_name, psyclone.parse.algorithm.ParsedCall._module_name, psyclone.parse.algorithm.KernelCall._module_name, psyclone.psyGen.CodedKern._module_name, psyclone.psyGen.Argument._module_name, and psyclone.psyir.nodes.psy_data_node.PSyDataNode._module_name.

Here is the caller graph for this function:

◆ node_str()

def psyclone.psyGen.CodedKern.node_str (   self,
  colour = True 
)
 Returns the name of this node with (optional) control codes
to generate coloured output in a terminal that supports it.

:param bool colour: whether or not to include colour control codes.

:returns: description of this node, possibly coloured.
:rtype: str

Reimplemented from psyclone.psyGen.Kern.

Definition at line 1487 of file psyGen.py.

1487  def node_str(self, colour=True):
1488  ''' Returns the name of this node with (optional) control codes
1489  to generate coloured output in a terminal that supports it.
1490 
1491  :param bool colour: whether or not to include colour control codes.
1492 
1493  :returns: description of this node, possibly coloured.
1494  :rtype: str
1495  '''
1496  return (self.coloured_name(colour) + " " + self.name + "(" +
1497  self.arguments.names + ") " + "[module_inline=" +
1498  str(self._module_inline) + "]")
1499 

References psyclone.psyGen.CodedKern._module_inline, psyclone.psyGen.Kern.arguments(), psyclone.psyir.nodes.call.Call.arguments(), psyclone.psyir.nodes.node.Node.coloured_name(), psyclone.domain.gocean.kernel.psyir.GOceanKernelMetadata.name, psyclone.domain.gocean.kernel.psyir.GOceanKernelMetadata.GridArg.name, psyclone.domain.gocean.transformations.gocean_const_loop_bounds_trans.GOConstLoopBoundsTrans.name(), psyclone.domain.gocean.transformations.gocean_move_iteration_boundaries_inside_kernel_trans.GOMoveIterationBoundariesInsideKernelTrans.name(), psyclone.domain.gocean.transformations.gocean_opencl_trans.GOOpenCLTrans.name(), psyclone.domain.lfric.kernel.lfric_kernel_metadata.LFRicKernelMetadata.name, psyclone.domain.nemo.transformations.create_nemo_invoke_schedule_trans.CreateNemoInvokeScheduleTrans.name(), psyclone.domain.nemo.transformations.create_nemo_psy_trans.CreateNemoPSyTrans.name(), psyclone.domain.nemo.transformations.nemo_allarrayrange2loop_trans.NemoAllArrayRange2LoopTrans.name(), psyclone.domain.nemo.transformations.nemo_arrayrange2loop_trans.NemoArrayRange2LoopTrans.name(), psyclone.domain.nemo.transformations.nemo_outerarrayrange2loop_trans.NemoOuterArrayRange2LoopTrans.name(), psyclone.dynamo0p3.DynamoPSy.name(), psyclone.expression.FunctionVar.name, psyclone.expression.NamedArg.name(), psyclone.gocean1p0.GOKernelGridArgument.name(), psyclone.gocean1p0.GOStencil.name(), psyclone.parse.algorithm.FileInfo.name(), psyclone.parse.algorithm.InvokeCall.name(), psyclone.parse.kernel.KernelProcedure.name(), psyclone.parse.kernel.KernelType.name(), psyclone.parse.module_info.ModuleInfo.name(), psyclone.psyad.transformations.assignment_trans.AssignmentTrans.name(), psyclone.psyGen.PSy.name(), psyclone.psyGen.Invoke.name(), psyclone.psyGen.Kern.name(), psyclone.psyGen.CodedKern.name, psyclone.psyGen.Argument.name(), psyclone.psyGen.Transformation.name(), psyclone.psyGen.DummyTransformation.name(), psyclone.psyir.nodes.container.Container.name, psyclone.psyir.nodes.member.Member.name, psyclone.psyir.nodes.reference.Reference.name(), psyclone.psyir.nodes.routine.Routine.name, psyclone.psyir.symbols.symbol.Symbol.name(), psyclone.psyir.transformations.allarrayaccess2loop_trans.AllArrayAccess2LoopTrans.name(), psyclone.psyir.transformations.arrayrange2loop_trans.ArrayRange2LoopTrans.name(), psyclone.psyir.transformations.fold_conditional_return_expressions_trans.FoldConditionalReturnExpressionsTrans.name(), psyclone.psyir.transformations.loop_trans.LoopTrans.name(), psyclone.psyir.transformations.omp_task_trans.OMPTaskTrans.name(), psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.name(), psyclone.transformations.OMPSingleTrans.name(), psyclone.transformations.OMPMasterTrans.name(), psyclone.transformations.OMPParallelTrans.name(), psyclone.transformations.MoveTrans.name(), psyclone.transformations.Dynamo0p3AsyncHaloExchangeTrans.name(), psyclone.transformations.Dynamo0p3KernelConstTrans.name(), psyclone.transformations.ACCEnterDataTrans.name(), psyclone.transformations.ACCRoutineTrans.name(), psyclone.transformations.ACCKernelsTrans.name(), psyclone.transformations.ACCDataTrans.name(), and psyclone.transformations.KernelImportsToArguments.name().

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

◆ opencl_options()

def psyclone.psyGen.CodedKern.opencl_options (   self)
:returns: dictionary of OpenCL options regarding the kernel.
:rtype: dictionary

Definition at line 1394 of file psyGen.py.

1394  def opencl_options(self):
1395  '''
1396  :returns: dictionary of OpenCL options regarding the kernel.
1397  :rtype: dictionary
1398  '''
1399  return self._opencl_options
1400 

References psyclone.psyGen.CodedKern._opencl_options.

◆ rename_and_write()

def psyclone.psyGen.CodedKern.rename_and_write (   self)
Writes the (transformed) AST of this kernel to file and resets the
'modified' flag to False. By default (config.kernel_naming ==
"multiple"), the kernel is re-named so as to be unique within
the kernel output directory stored within the configuration
object. Alternatively, if config.kernel_naming is "single"
then no re-naming and output is performed if there is already
a transformed copy of the kernel in the output dir. (In this
case a check is performed that the transformed kernel already
present is identical to the one that we would otherwise write
to file. If this is not the case then we raise a GenerationError.)

:raises GenerationError: if config.kernel_naming == "single" and a \
                         different, transformed version of this \
                         kernel is already in the output directory.
:raises NotImplementedError: if the kernel has been transformed but \
                             is also flagged for module-inlining.

Definition at line 1607 of file psyGen.py.

1607  def rename_and_write(self):
1608  '''
1609  Writes the (transformed) AST of this kernel to file and resets the
1610  'modified' flag to False. By default (config.kernel_naming ==
1611  "multiple"), the kernel is re-named so as to be unique within
1612  the kernel output directory stored within the configuration
1613  object. Alternatively, if config.kernel_naming is "single"
1614  then no re-naming and output is performed if there is already
1615  a transformed copy of the kernel in the output dir. (In this
1616  case a check is performed that the transformed kernel already
1617  present is identical to the one that we would otherwise write
1618  to file. If this is not the case then we raise a GenerationError.)
1619 
1620  :raises GenerationError: if config.kernel_naming == "single" and a \
1621  different, transformed version of this \
1622  kernel is already in the output directory.
1623  :raises NotImplementedError: if the kernel has been transformed but \
1624  is also flagged for module-inlining.
1625 
1626  '''
1627  from psyclone.line_length import FortLineLength
1628 
1629  config = Config.get()
1630 
1631  # If this kernel has not been transformed we do nothing, also if the
1632  # kernel has been module-inlined, the routine already exist in the
1633  # PSyIR and we don't need to generate a new file with it.
1634  if not self.modified or self.module_inline:
1635  return
1636 
1637  # Remove any "_mod" if the file follows the PSyclone naming convention
1638  orig_mod_name = self.module_name[:]
1639  if orig_mod_name.lower().endswith("_mod"):
1640  old_base_name = orig_mod_name[:-4]
1641  else:
1642  old_base_name = orig_mod_name[:]
1643 
1644  # We could create a hash of a string built from the name of the
1645  # Algorithm (module), the name/position of the Invoke and the
1646  # index of this kernel within that Invoke. However, that creates
1647  # a very long name so we simply ensure that kernel names are unique
1648  # within the user-supplied kernel-output directory.
1649  name_idx = -1
1650  fdesc = None
1651  while not fdesc:
1652  name_idx += 1
1653  new_suffix = ""
1654 
1655  new_suffix += f"_{name_idx}"
1656  new_name = old_base_name + new_suffix + "_mod.f90"
1657 
1658  try:
1659  # Atomically attempt to open the new kernel file (in case
1660  # this is part of a parallel build)
1661  fdesc = os.open(
1662  os.path.join(config.kernel_output_dir, new_name),
1663  os.O_CREAT | os.O_WRONLY | os.O_EXCL)
1664  except (OSError, IOError):
1665  # The os.O_CREATE and os.O_EXCL flags in combination mean
1666  # that open() raises an error if the file exists
1667  if config.kernel_naming == "single":
1668  # If the kernel-renaming scheme is such that we only ever
1669  # create one copy of a transformed kernel then we're done
1670  break
1671  continue
1672 
1673  # Use the suffix we have determined to rename all relevant quantities
1674  # within the AST of the kernel code.
1675  self._rename_psyir(new_suffix)
1676 
1677  # Kernel is now self-consistent so unset the modified flag
1678  self.modified = False
1679 
1680  # If we reach this point the kernel needs to be written out into a
1681  # file using a PSyIR back-end. At the moment there is no way to choose
1682  # which back-end to use, so simply use the Fortran one (and limit the
1683  # line length).
1684  fortran_writer = FortranWriter(
1685  check_global_constraints=config.backend_checks_enabled)
1686  # Start from the root of the schedule as we want to output
1687  # any module information surrounding the kernel subroutine
1688  # as well as the subroutine itself.
1689  new_kern_code = fortran_writer(self.get_kernel_schedule().root)
1690  fll = FortLineLength()
1691  new_kern_code = fll.process(new_kern_code)
1692 
1693  if not fdesc:
1694  # If we've not got a file descriptor at this point then that's
1695  # because the file already exists and the kernel-naming scheme
1696  # ("single") means we're not creating a new one.
1697  # Check that what we've got is the same as what's in the file
1698  with open(os.path.join(config.kernel_output_dir,
1699  new_name), "r") as ffile:
1700  kern_code = ffile.read()
1701  if kern_code != new_kern_code:
1702  raise GenerationError(
1703  f"A transformed version of this Kernel "
1704  f"'{self._module_name + '''.f90'''}' already exists "
1705  f"in the kernel-output directory "
1706  f"({config.kernel_output_dir}) but is not the "
1707  f"same as the current, transformed kernel and the "
1708  f"kernel-renaming scheme is set to "
1709  f"'{config.kernel_naming}'. (If you wish to"
1710  f" generate a new, unique kernel for every kernel "
1711  f"that is transformed then use "
1712  f"'--kernel-renaming multiple'.)")
1713  else:
1714  # Write the modified AST out to file
1715  os.write(fdesc, new_kern_code.encode())
1716  # Close the new kernel file
1717  os.close(fdesc)
1718 

References psyclone.dynamo0p3.DynKernelArgument._module_name, psyclone.parse.algorithm.ParsedCall._module_name, psyclone.parse.algorithm.KernelCall._module_name, psyclone.psyGen.CodedKern._module_name, psyclone.psyGen.Argument._module_name, psyclone.psyir.nodes.psy_data_node.PSyDataNode._module_name, psyclone.psyGen.CodedKern._new_name(), psyclone.psyGen.CodedKern._rename_psyir(), psyclone.domain.lfric.lfric_kern.LFRicKern.get_kernel_schedule(), psyclone.gocean1p0.GOKern.get_kernel_schedule(), psyclone.psyGen.CodedKern.get_kernel_schedule(), psyclone.psyGen.CodedKern.modified, psyclone.psyGen.CodedKern.module_inline(), psyclone.parse.algorithm.ParsedCall.module_name(), psyclone.psyGen.CodedKern.module_name(), psyclone.psyGen.Argument.module_name(), psyclone.psyir.nodes.psy_data_node.PSyDataNode.module_name, psyclone.domain.gocean.kernel.psyir.GOceanKernelMetadata.name, psyclone.domain.gocean.kernel.psyir.GOceanKernelMetadata.GridArg.name, psyclone.domain.gocean.transformations.gocean_const_loop_bounds_trans.GOConstLoopBoundsTrans.name(), psyclone.domain.gocean.transformations.gocean_move_iteration_boundaries_inside_kernel_trans.GOMoveIterationBoundariesInsideKernelTrans.name(), psyclone.domain.gocean.transformations.gocean_opencl_trans.GOOpenCLTrans.name(), psyclone.domain.lfric.kernel.lfric_kernel_metadata.LFRicKernelMetadata.name, psyclone.domain.nemo.transformations.create_nemo_invoke_schedule_trans.CreateNemoInvokeScheduleTrans.name(), psyclone.domain.nemo.transformations.create_nemo_psy_trans.CreateNemoPSyTrans.name(), psyclone.domain.nemo.transformations.nemo_allarrayrange2loop_trans.NemoAllArrayRange2LoopTrans.name(), psyclone.domain.nemo.transformations.nemo_arrayrange2loop_trans.NemoArrayRange2LoopTrans.name(), psyclone.domain.nemo.transformations.nemo_outerarrayrange2loop_trans.NemoOuterArrayRange2LoopTrans.name(), psyclone.dynamo0p3.DynamoPSy.name(), psyclone.expression.FunctionVar.name, psyclone.expression.NamedArg.name(), psyclone.gocean1p0.GOKernelGridArgument.name(), psyclone.gocean1p0.GOStencil.name(), psyclone.parse.algorithm.FileInfo.name(), psyclone.parse.algorithm.InvokeCall.name(), psyclone.parse.kernel.KernelProcedure.name(), psyclone.parse.kernel.KernelType.name(), psyclone.parse.module_info.ModuleInfo.name(), psyclone.psyad.transformations.assignment_trans.AssignmentTrans.name(), psyclone.psyGen.PSy.name(), psyclone.psyGen.Invoke.name(), psyclone.psyGen.Kern.name(), psyclone.psyGen.CodedKern.name, psyclone.psyGen.Argument.name(), psyclone.psyGen.Transformation.name(), psyclone.psyGen.DummyTransformation.name(), psyclone.psyir.nodes.container.Container.name, psyclone.psyir.nodes.member.Member.name, psyclone.psyir.nodes.reference.Reference.name(), psyclone.psyir.nodes.routine.Routine.name, psyclone.psyir.symbols.symbol.Symbol.name(), psyclone.psyir.transformations.allarrayaccess2loop_trans.AllArrayAccess2LoopTrans.name(), psyclone.psyir.transformations.arrayrange2loop_trans.ArrayRange2LoopTrans.name(), psyclone.psyir.transformations.fold_conditional_return_expressions_trans.FoldConditionalReturnExpressionsTrans.name(), psyclone.psyir.transformations.loop_trans.LoopTrans.name(), psyclone.psyir.transformations.omp_task_trans.OMPTaskTrans.name(), psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.name(), psyclone.transformations.OMPSingleTrans.name(), psyclone.transformations.OMPMasterTrans.name(), psyclone.transformations.OMPParallelTrans.name(), psyclone.transformations.MoveTrans.name(), psyclone.transformations.Dynamo0p3AsyncHaloExchangeTrans.name(), psyclone.transformations.Dynamo0p3KernelConstTrans.name(), psyclone.transformations.ACCEnterDataTrans.name(), psyclone.transformations.ACCRoutineTrans.name(), psyclone.transformations.ACCKernelsTrans.name(), psyclone.transformations.ACCDataTrans.name(), and psyclone.transformations.KernelImportsToArguments.name().

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

◆ set_opencl_options()

def psyclone.psyGen.CodedKern.set_opencl_options (   self,
  options 
)
Validate and store a set of options associated with the Kernel to
tune the OpenCL code generation.

:param options: a set of options to tune the OpenCL code.
:type options: dictionary of <string>:<value>

Definition at line 1401 of file psyGen.py.

1401  def set_opencl_options(self, options):
1402  '''
1403  Validate and store a set of options associated with the Kernel to
1404  tune the OpenCL code generation.
1405 
1406  :param options: a set of options to tune the OpenCL code.
1407  :type options: dictionary of <string>:<value>
1408 
1409  '''
1410  valid_opencl_kernel_options = ['local_size', 'queue_number']
1411 
1412  # Validate that the options given are supported
1413  for key, value in options.items():
1414  if key in valid_opencl_kernel_options:
1415  if key == "local_size":
1416  if not isinstance(value, int):
1417  raise TypeError(
1418  "CodedKern OpenCL option 'local_size' should be "
1419  "an integer.")
1420  if key == "queue_number":
1421  if not isinstance(value, int):
1422  raise TypeError(
1423  "CodedKern OpenCL option 'queue_number' should be "
1424  "an integer.")
1425  else:
1426  raise AttributeError(
1427  f"CodedKern does not support the OpenCL option '{key}'. "
1428  f"The supported options are: "
1429  f"{valid_opencl_kernel_options}.")
1430 
1431  self._opencl_options[key] = value
1432 

References psyclone.domain.common.algorithm.psyir.AlgorithmInvokeCall._name, psyclone.domain.gocean.kernel.psyir.GOceanKernelMetadata._name, psyclone.domain.gocean.kernel.psyir.GOceanKernelMetadata.GridArg._name, psyclone.domain.lfric.kernel.lfric_kernel_metadata.LFRicKernelMetadata._name, psyclone.dynamo0p3.DynFuncDescriptor03._name, psyclone.expression.NamedArg._name, psyclone.gocean1p0.GOKernelGridArgument._name, psyclone.gocean1p0.GOStencil._name, psyclone.nemo.NemoInvoke._name, psyclone.nemo.NemoPSy._name, psyclone.parse.algorithm.FileInfo._name, psyclone.parse.algorithm.InvokeCall._name, psyclone.parse.kernel.KernelProcedure._name, psyclone.parse.kernel.KernelType._name, psyclone.parse.module_info.ModuleInfo._name, psyclone.psyGen.PSy._name, psyclone.psyGen.Invoke._name, psyclone.psyGen.Kern._name, psyclone.psyGen.Argument._name, psyclone.psyir.nodes.container.Container._name, psyclone.psyir.nodes.routine.Routine._name, psyclone.psyir.symbols.symbol.Symbol._name, and psyclone.psyGen.CodedKern._opencl_options.


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