Composer API (pystencilssfg.composer)

Contents

Composer API (pystencilssfg.composer)#

class pystencilssfg.composer.SfgComposer(sfg)#

Primary interface for constructing source files in pystencils-sfg.

The SfgComposer combines the SfgBasicComposer for the basic components (kernel namespaces, includes, definitions, and functions) and the SfgClassComposer for constructing struct s and class es.

Parameters:

sfg (SfgContext | SfgBasicComposer)

class pystencilssfg.composer.SfgIComposer(ctx)#
Parameters:

ctx (SfgContext)

class pystencilssfg.composer.SfgBasicComposer(sfg)#

Composer for basic source components, and base class for all composer mix-ins.

Parameters:

sfg (SfgContext | SfgIComposer)

prelude(content, end='\\n')#

Append a string to the prelude comment, to be printed at the top of both generated files.

The string should not contain C/C++ comment delimiters, since these will be added automatically during code generation.

Example:
>>> sfg.prelude("This file was generated using pystencils-sfg; do not modify it directly!")

will appear in the generated files as

/*
 * This file was generated using pystencils-sfg; do not modify it directly!
 */
Parameters:
code(*code, impl=False)#

Add arbitrary lines of code to the generated header file.

Example:
>>> sfg.code(
...     "#define PI 3.14  // more than enough for engineers",
...     "using namespace std;"
... )

will appear as

#define PI 3.14 // more than enough for engineers
using namespace std;
Parameters:
  • code (str) – Sequence of code strings to be written to the output file

  • impl (bool) – If True, write the code to the implementation file; otherwise, to the header file.

namespace(namespace)#

Enter a new namespace block.

Calling namespace as a regular function will open a new namespace as a child of the currently active namespace; this new namespace will then become active instead. Using namespace as a context manager will instead activate the given namespace only for the length of the with block.

Parameters:

namespace (str) – Qualified name of the namespace

Example:

The following calls will set the current namespace to outer::inner for the remaining code generation run:

sfg.namespace("outer")
sfg.namespace("inner")

Subsequent calls to namespace can only create further nested namespaces.

To step back out of a namespace, namespace can also be used as a context manager:

with sfg.namespace("detail"):
    ...

This way, code generated inside the with region is placed in the detail namespace, and code after this block will again live in the enclosing namespace.

generate(generator)#

Invoke a custom code generator with the underlying context.

Parameters:

generator (CustomGenerator)

property kernels: KernelsAdder#

The default kernel namespace.

Add kernels like:

sfg.kernels.add(ast, "kernel_name")
sfg.kernels.create(assignments, "kernel_name", config)
kernel_namespace(name)#

Return a view on a kernel namespace in order to add kernels to it.

Return type:

KernelsAdder

Parameters:

name (str)

include(header, private=False)#

Include a header file.

Parameters:
  • header_file – Path to the header file. Enclose in <> for a system header.

  • private (bool) – If True, in header-implementation code generation, the header file is only included in the implementation file.

  • header (str | HeaderFile)

Example:
>>> sfg.include("<vector>")
>>> sfg.include("custom.h")

will be printed as

#include <vector>
#include "custom.h"
kernel_function(name, kernel)#

Create a function comprising just a single kernel call.

Parameters:
  • ast_or_kernel_handle – Either a pystencils AST, or a kernel handle for an already registered AST.

  • name (str)

  • kernel (Kernel | SfgKernelHandle)

function(name, return_type=None)#

Add a function.

The syntax of this function adder uses a chain of two calls to mimic C++ syntax:

sfg.function("FunctionName")(
    # Function Body
)

The function body is constructed via sequencing (see make_sequence).

Return type:

SfgFunctionSequencer

Parameters:
call(kernel_handle)#

Use inside a function body to directly call a kernel.

When using call, the given kernel will simply be called as a function. To invoke a GPU kernel on a specified launch grid, use gpu_invoke instead.

Parameters:

kernel_handle (SfgKernelHandle) – Handle to a kernel previously added to some kernel namespace.

Return type:

SfgCallTreeNode

seq(*args)#

Syntax sequencing. For details, see make_sequence

Return type:

SfgSequence

Parameters:

args (tuple | str | SfgCallTreeNode | SfgNodeBuilder)

params(*args)#

Use inside a function body to add parameters to the function.

Return type:

SfgFunctionParams

Parameters:

args (AugExpr)

require(*incls)#

Use inside a function body to require the inclusion of headers.

Return type:

SfgRequireIncludes

Parameters:

incls (str | HeaderFile)

var(name, dtype)#

Create a variable with given name and data type.

Return type:

AugExpr

Parameters:
vars(names, dtype)#

Create multiple variables with given names and the same data type.

Example:

Return type:

tuple[AugExpr, ...]

Parameters:
>>> sfg.vars("x, y, z", "float32")
(x, y, z)
init(lhs)#

Create a C++ in-place initialization.

Usage:

obj = sfg.var("obj", "SomeClass")
sfg.init(obj)(arg1, arg2, arg3)

becomes

SomeClass obj { arg1, arg2, arg3 };
Parameters:

lhs (AugExpr | SfgVar | TypedSymbol)

expr(fmt, *deps, **kwdeps)#

Create an expression while keeping track of variables it depends on.

This method is meant to be used similarly to str.format; in fact, it calls str.format internally and therefore supports all of its formatting features. In addition, however, the format arguments are scanned for variables (e.g. created using var), which are attached to the expression. This way, pystencils-sfg keeps track of any variables an expression depends on.

Example:
>>> x, y, z, w = sfg.vars("x, y, z, w", "float32")
>>> expr = sfg.expr("{} + {} * {}", x, y, z)
>>> expr
x + y * z

You can look at the expression’s dependencies:

>>> sorted(expr.depends, key=lambda v: v.name)
[x: float32, y: float32, z: float32]

If you use an existing expression to create a larger one, the new expression inherits all variables from its parts:

>>> expr2 = sfg.expr("{} + {}", expr, w)
>>> expr2
x + y * z + w
>>> sorted(expr2.depends, key=lambda v: v.name)
[w: float32, x: float32, y: float32, z: float32]
Return type:

AugExpr

Parameters:

fmt (str)

property branch: SfgBranchBuilder#

Use inside a function body to create an if/else conditonal branch.

The syntax is:

sfg.branch("condition")(
    # then-body
)(
    # else-body (may be omitted)
)
switch(switch_arg, autobreak=True)#

Use inside a function to construct a switch-case statement.

Parameters:
Return type:

SfgSwitchBuilder

map_field(field, index_provider, cast_indexing_symbols=True)#

Map a pystencils field to a field data structure, from which pointers, sizes and strides should be extracted.

Parameters:
  • field (Field) – The pystencils field to be mapped

  • index_provider (SupportsFieldExtraction) – An object that provides the field indexing information

  • cast_indexing_symbols (bool) – Whether to always introduce explicit casts for indexing symbols

Return type:

SfgDeferredFieldMapping

set_param(param, expr)#

Set a kernel parameter to an expression.

Code setting the parameter will only be generated if the parameter is actually alive (i.e. required by some kernel, and not yet set) at the point this method is called.

Parameters:
map_vector(lhs_components, rhs)#

Extracts scalar numerical values from a vector data type.

Parameters:
class pystencilssfg.composer.SfgClassComposer#

Composer for classes and structs.

This class cannot be instantiated on its own but must be mixed in with SfgBasicComposer. Its interface is exposed by SfgComposer.

class VisibilityBlockSequencer(visibility)#

Represent a visibility block in the composer syntax.

Returned by private, public, and protected.

Parameters:

visibility (SfgVisibility)

class ConstructorBuilder(*params)#

Composer syntax for constructor building.

Returned by constructor.

Parameters:

params (VarLike)

init(var)#

Add an initialization expression to the constructor’s initializer list.

Parameters:

var (AugExpr | SfgVar | TypedSymbol | str)

body(body)#

Define the constructor body

Parameters:

body (str)

klass(class_name, bases=())#

Create a class and add it to the underlying context.

Parameters:
  • class_name (str) – Name of the class

  • bases (Sequence[str]) – List of base classes

struct(class_name, bases=())#

Create a struct and add it to the underlying context.

Parameters:
  • class_name (str) – Name of the struct

  • bases (Sequence[str]) – List of base classes

numpy_struct(name, dtype, add_constructor=True)#

Add a numpy structured data type as a C++ struct

Returns:

The created class object

Parameters:
property public: VisibilityBlockSequencer#

Create a public visibility block in a class body

property protected: VisibilityBlockSequencer#

Create a protected visibility block in a class or struct body

property private: VisibilityBlockSequencer#

Create a private visibility block in a class or struct body

constructor(*params)#

In a class or struct body or visibility block, add a constructor.

Parameters:

params (AugExpr | SfgVar | TypedSymbol) – List of constructor parameters

method(name)#

In a class or struct body or visibility block, add a method. The usage is similar to SfgBasicComposer.function.

Parameters:

name (str) – The method name

class pystencilssfg.composer.SfgGpuComposer#

Composer mix-in providing methods to generate GPU kernel invocations.

gpu_invoke(kernel_handle: SfgKernelHandle, **kwargs)#

Invoke a GPU kernel with launch configuration parameters depending on its code generator configuration.

The overloads of this method are listed below. They all (partially) mirror the CUDA and HIP kernel<<< Gs, Bs, Sm, St >>>() syntax; for details on the launch configuration arguments, refer to Launch Configurations in CUDA or Launch Configurations in HIP.

gpu_invoke(kernel_handle: SfgKernelHandle, *, grid_size: ExprLike, block_size: ExprLike, shared_memory_bytes: ExprLike = '0', stream: ExprLike | None = None) SfgCallTreeNode

Invoke a GPU kernel with a manual launch grid.

Requires that the kernel was generated with manual_launch_grid set to True.

gpu_invoke(self, kernel_handle: SfgKernelHandle, *, shared_memory_bytes: ExprLike = '0', stream: ExprLike | None = None) SfgCallTreeNode

Invoke a GPU kernel with an automatic launch grid.

This signature accepts kernels generated with an indexing scheme that causes the launch grid to be determined automatically, such as Blockwise4D.

gpu_invoke(self, kernel_handle: SfgKernelHandle, *, block_size: ExprLike | None = None, shared_memory_bytes: ExprLike = '0', stream: ExprLike | None = None) SfgCallTreeNode

Invoke a GPU kernel with a dynamic launch grid.

This signature accepts kernels generated with an indexing scheme that permits a user-defined blocks size, such as Linear3D. The grid size is calculated automatically by dividing the number of work items in each dimension by the block size, rounding up.

Custom Generators#

class pystencilssfg.composer.custom.CustomGenerator#

Abstract base class for custom code generators that may be passed to SfgBasicComposer.generate.

Helper Methods and Builders#

pystencilssfg.composer.basic_composer.make_sequence(*args)#

Construct a sequence of C++ code from various kinds of arguments.

make_sequence is ubiquitous throughout the function building front-end; among others, it powers the syntax of SfgBasicComposer.function and SfgBasicComposer.branch.

make_sequence constructs an abstract syntax tree for code within a function body, accepting various types of arguments which then get turned into C++ code. These are :rtype: SfgSequence

  • Strings (str) are printed as-is

  • Tuples (tuple) signify blocks, i.e. C++ code regions enclosed in { }

  • Sub-ASTs and AST builders, which are often produced by the syntactic sugar and factory methods of SfgComposer.

Example:
tree = make_sequence(
    "int a = 0;",
    "int b = 1;",
    (
        "int tmp = b;",
        "b = a;",
        "a = tmp;"
    ),
    SfgKernelCall(kernel_handle)
)

sfg.context.add_function("myFunction", tree)

will translate to

void myFunction() {
    int a = 0;
    int b = 0;
    {
        int tmp = b;
        b = a;
        a = tmp;
    }
    kernels::kernel( ... );
}
Parameters:

args (tuple | str | AugExpr | SfgVar | TypedSymbol | SfgCallTreeNode | SfgNodeBuilder)

Return type:

SfgSequence

class pystencilssfg.composer.basic_composer.KernelsAdder(cursor, knamespace)#

Handle on a kernel namespace that permits registering kernels.

Parameters:
inline()#

Generate kernel definitions inline in the header file.

Return type:

KernelsAdder

add(kernel, name=None)#

Adds an existing pystencils AST to this namespace. If a name is specified, the AST’s function name is changed.

Parameters:
create(assignments, name=None, config=None)#

Creates a new pystencils kernel from a list of assignments and a configuration. This is a wrapper around create_kernel with a subsequent call to add.

Parameters:
class pystencilssfg.composer.basic_composer.SfgFunctionSequencer(cursor, name)#

Sequencer for constructing functions.

Parameters:
attr(*attrs)#

Add attributes to this function

Parameters:

attrs (str)

constexpr()#

Mark this function as constexpr.

inline()#

Mark this function as inline.

params(*args)#

Specify the parameters for this function.

Use this to manually specify the function’s parameter list.

If any free variables collected from the function body are not contained in the parameter list, an error will be raised.

Parameters:

args (AugExpr | SfgVar | TypedSymbol)

returns(rtype)#

Set the return type of the function

Parameters:

rtype (str | type | dtype | PsType)

class pystencilssfg.composer.basic_composer.SfgNodeBuilder#

Base class for node builders used by the composer

class pystencilssfg.composer.basic_composer.SfgBranchBuilder#

Multi-call builder for C++ if/else statements.

class pystencilssfg.composer.basic_composer.SfgSwitchBuilder(switch_arg, autobreak=True)#

Builder for C++ switches.

Parameters:
  • switch_arg (ExprLike)

  • autobreak (bool)

class pystencilssfg.composer.class_composer.SfgMethodSequencer(cursor, name)#
Parameters:
const()#

Mark this method as const.

static()#

Mark this method as static.

virtual()#

Mark this method as virtual.

override()#

Mark this method as override.

attr(*attrs)#

Add attributes to this function

Parameters:

attrs (str)

constexpr()#

Mark this function as constexpr.

inline()#

Mark this function as inline.

params(*args)#

Specify the parameters for this function.

Use this to manually specify the function’s parameter list.

If any free variables collected from the function body are not contained in the parameter list, an error will be raised.

Parameters:

args (AugExpr | SfgVar | TypedSymbol)

returns(rtype)#

Set the return type of the function

Parameters:

rtype (str | type | dtype | PsType)

Context and Cursor#

class pystencilssfg.context.SfgContext(header_file, impl_file, namespace=None, codestyle=None, clang_format_opts=None, argv=None, project_info=None)#

Manages context information during the execution of a generator script.

Parameters:
property argv: Sequence[str]#

If this context was created by a pystencilssfg.SourceFileGenerator, provides the command line arguments given to the generator script, with configuration arguments for the code generator stripped away.

Otherwise, throws an exception.

property project_info: Any#

Project-specific information provided by a build system.

property outer_namespace: str | None#

Outer code namespace. Set by constructor argument outer_namespace.

property codestyle: CodeStyle#

The code style object for this generation context.

class pystencilssfg.context.SfgCursor(ctx, namespace)#

Cursor that tracks the current location in the source file(s) during execution of the generator script.

Parameters: