Kernel Translation¶
- class pystencils.backend.kernelcreation.KernelCreationContext(default_dtype=PsIeeeFloatType(width=64, const=False), index_dtype=PsIntegerType(width=64, signed=True, const=False))¶
Manages the translation process from the SymPy frontend to the backend AST, and collects all necessary information for the translation:
Data Types: The kernel creation context manages the default data types for loop limits and counters, index calculations, and the typifier.
Symbols: The context maintains a symbol table, keeping track of all symbols encountered during kernel translation together with their types.
Fields and Arrays: The context collects all fields encountered during code generation, applies a few consistency checks to them, and manages their associated arrays.
Iteration Space: The context manages the iteration space of the kernel currently being translated.
Constraints: The context collects all kernel parameter constraints introduced during the translation process.
Required Headers: The context collects all header files required for the kernel to run.
- Parameters:
default_dtype (PsNumericType) –
index_dtype (PsIntegerType) –
- get_symbol(name, dtype=None)¶
Retrieve the symbol with the given name and data type from the symbol table.
If no symbol named
name
exists, a new symbol with the given data type is created.If a symbol with the given
name
already exists anddtype
is not None, the given data type will be applied to it, and it is returned. If the symbol already has a different data type, an error will be raised.If the symbol already exists and
dtype
is None, the existing symbol is returned without checking or altering its data type.
- find_symbol(name)¶
Find a symbol with the given name in the symbol table, if it exists.
- add_symbol(symbol)¶
Add an existing symbol to the symbol table.
If a symbol with the same name already exists, an error will be raised.
- Parameters:
symbol (PsSymbol) –
- replace_symbol(old, new)¶
Replace one symbol by another.
The two symbols
old
andnew
must have the same name, but may have different data types.
- duplicate_symbol(symb)¶
Canonically duplicates the given symbol.
A new symbol with the same data type, and new name
symb.name + "__<counter>"
is created, added to the symbol table, and returned. Thecounter
reflects the number of previously created duplicates of this symbol.
- add_field(field)¶
Add the given field to the context’s fields collection.
This method adds the passed
field
to the context’s field collection, which is accesible through the fields member, and creates an array representation of the field, which is retrievable through get_array. Before adding the field to the collection, various sanity and constraint checks are applied.- Parameters:
field (Field) –
- class pystencils.backend.kernelcreation.AstFactory(ctx)¶
Factory providing a convenient interface for building syntax trees.
The AstFactory uses the defaults provided by the given KernelCreationContext to quickly create AST nodes. Depending on context (numerical, loop indexing, etc.), symbols and constants receive either
ctx.default_dtype
orctx.index_dtype
.- Parameters:
ctx (
KernelCreationContext
) – The kernel creation context
- parse_sympy(sp_obj)¶
Parse a SymPy expression or assignment through FreezeExpressions and Typifier.
The expression or assignment will be typified in a numerical context, using the kernel creation context’s default_dtype.
- Parameters:
sp_obj (
Expr
|AssignmentBase
) – A SymPy expression or assignment- Return type:
- parse_index(idx)¶
Parse the given object as an expression with data type ctx.index_dtype.
- Parameters:
idx (PsExpression | PsSymbol | PsConstant | Expr | int | integer) –
- parse_slice(slic, upper_limit=None)¶
Parse a slice to obtain start, stop and step expressions for a loop or iteration space dimension.
The slice entries may be instances of PsExpression, PsSymbol or PsConstant, in which case they must typify with the kernel creation context’s
index_dtype
. They may also be sympy expressions or integer constants, in which case they are parsed to AST objects and must also typify with the kernel creation context’sindex_dtype
.If the slice’s
stop
member is None or a negative int, upper_limit must be specified, which is then used as the upper iteration limit as eitherupper_limit
orupper_limit - stop
.- Parameters:
- Return type:
- loop(ctr_name, iteration_slice, body)¶
Create a loop from a slice.
- loop_nest(counters, slices, body)¶
Create a loop nest from a sequence of slices.
Example: This snippet creates a 3D loop nest with ten iterations in each dimension:
>>> from pystencils import make_slice >>> ctx = KernelCreationContext() >>> factory = AstFactory(ctx) >>> loop = factory.loop_nest(("i", "j", "k"), make_slice[:10,:10,:10], PsBlock([]))
- loops_from_ispace(ispace, body, loop_order=None)¶
Create a loop nest from a dense iteration space.
- class pystencils.backend.kernelcreation.KernelAnalysis(ctx)¶
General analysis pass over a kernel expressed using the SymPy frontend.
The kernel analysis fulfills two tasks. It checks the SymPy input for consistency, and populates the context with required knowledge about the kernel.
A KernelAnalysis object may be called at most once.
Consistency and Constraints
The following checks are performed:
SSA Form: The given assignments must be in single-assignment form; each symbol must be written at most once.
Independence of Accesses: To avoid loop-carried dependencies, each field may be written at most once at each index, and if a field is written at some location with index i, it may only be read with index i in the same location.
Independence of Writes: A weaker requirement than access independence; each field may only be written once at each index.
Dimension of index fields: Index fields occuring in the kernel must have exactly one spatial dimension.
Knowledge Collection
- The following knowledge is collected into the context:
The set of fields accessed in the kernel
- Parameters:
ctx (KernelCreationContext) –
- class pystencils.backend.kernelcreation.FreezeExpressions(ctx)¶
Convert expressions and kernels expressed in the SymPy language to the code generator’s internal representation.
This class accepts a subset of the SymPy symbolic algebra language complemented with the extensions implemented in pystencils.sympyextensions, and converts it to the abstract syntax tree representation of the pystencils code generator. It is invoked early during the code generation process.
TODO: Document the full set of supported SymPy features, with restrictions and caveats TODO: Properly document the SymPy extensions provided by pystencils
- Parameters:
ctx (KernelCreationContext) –
- map_Function(func)¶
Map SymPy function calls by mapping sympy function classes to backend-supported function symbols.
If applicable, functions are mapped to binary operators, e.g. backend.ast.expressions.PsBitwiseXor. Other SymPy functions are frozen to an instance of nbackend.functions.PsFunction.
- Return type:
- Parameters:
func (Function) –
- class pystencils.backend.kernelcreation.Typifier(ctx)¶
Apply data types to expressions.
Contextual Typing
The Typifier will traverse the AST and apply a contextual typing scheme to figure out the data types of all encountered expressions. To this end, it covers each expression tree with a set of disjoint typing contexts. All nodes covered by the same typing context must have the same type.
Starting from an expression’s root, a typing context is implicitly expanded through the recursive descent into a node’s children. In particular, a child is typified within the same context as its parent if the node’s semantics require parent and child to have the same type (e.g. at arithmetic operators, mathematical functions, etc.). If a node’s child is required to have a different type, a new context is opened.
For each typing context, its target type is prescribed by the first node encountered during traversal whose type is fixed according to its typing rules. All other nodes covered by the context must share that type.
The types of arithmetic operators, mathematical functions, and untyped constants are inferred from their context’s target type. If one of these is encountered while no target type is set yet in the context, the expression is deferred by storing it in the context, and will be assigned a type as soon as the target type is fixed.
Typing Rules
The following general rules apply:
The context’s default_dtype is applied to all untyped symbols
By default, all expressions receive a
const
type unless they occur on a (non-declaration) assignment’s left-hand side
Typing of symbol expressions
Some expressions (PsSymbolExpr, PsArrayAccess) encapsulate symbols and inherit their data types, but not necessarily their const-qualification. A symbol with non-
const
type may occur in a PsSymbolExpr withconst
type, and an array base pointer with non-const
base type may be nested in aconst
PsArrayAccess, but not vice versa.- Parameters:
ctx (KernelCreationContext) –
- visit(node)¶
Recursive processing of structural nodes
- visit_expr(expr, tc)¶
Recursive processing of expression nodes.
This method opens, expands, and closes typing contexts according to the respective expression’s typing rules. It may add or check restrictions only when opening or closing a type context.
The actual type inference and checking during context expansion are performed by the methods of TypeContext.
visit_expr
tells the typing context how to handle an expression by calling eitherapply_dtype
orinfer_dtype
.- Return type:
- Parameters:
expr (PsExpression) –
tc (TypeContext) –