This module provides the AST. Subclass Context and override the various methods to allow minivect visitors over the AST, to promote and map types, etc. Subclass and override ASTBuilder‘s methods to provide alternative AST nodes or different implementations.
Bases: object
Use this to document class attributes for Sphinx
Bases: object
A context that knows how to map ASTs back and forth, how to wrap nodes and types, and how to instantiate a code generator for specialization.
An opaque_node or foreign node is a node that is not from our AST, and a normal node is one that has a interface compatible with ours.
To provide custom functionality, set the following attributes, or subclass this class.
Parameters: |
|
---|
The code generator class that is used to generate code. The default is minivect.codegen.CodeGen
The code generator that generates code to dispose of any garbage (e.g. intermediate object temporaries). The default is minivect.codegen.CodeGenCleanup
The code writer that the code generator writes its generated code to. This may be strings or arbitrary objects. The default is minivect.minicode.CodeWriter, which accepts arbitrary objects.
A formatter to format the generated code.
The default is minivect.minicode.CodeFormatter, which returns a list of objects written. Set this to minivect.minicode.CodeStringFormatter to have the strings joined together.
A specializer mixin class that can override or intercept functionality. This class should likely participate cooperatively in MI.
A specializer mixin class that resolves wrapped miniasts in a foreign AST. This is only needed if you are using NodeWrapper, which wraps a miniast somewhere at the leaves.
Use subclass CContext to get the defaults for C code generation.
alias of FinalSpecializer
Specialize the given AST with all given specializers and return an iterable of generated code in the form of (specializer, new_ast, codewriter, code_obj)
The code_obj is the generated code (e.g. a string of C code), depending on the code formatter used.
Bases: minivect.miniast.Context
Set defaults for C code generation.
alias of VectorCodegen
alias of CCodeWriter
alias of CCodeStringFormatter
Bases: minivect.miniast.Context
Context with default for LLVM code generation
alias of LLVMCodeGen
Bases: object
This class is used to build up a minivect AST. It can be used by a user from a transform or otherwise, but the important bit is that we use it in our code to build up an AST that can be overridden by the user, and which makes it convenient to build up complex ASTs concisely.
Create a new function.
Parameters: |
|
---|
Convenience method for building a minivect function
Create a (compound) function argument consisting of one or multiple argument Variables.
Generate a call to the given function (a FuncNameNode) of minivect.minitypes.FunctionType or a pointer to a function type and the given arguments.
This node wraps the given AST expression in an NDIterate node, which will be expanded by the specializers to one or several loops.
Create a for loop node.
Parameters: |
|
---|
Create a single upwards for loop, typically used from a specializer to replace an NDIterate node.
Parameters: |
|
---|
Annotate the for loop with an OpenMP parallel for clause.
Parameters: | if_clause – the expression node that determines whether the parallel section is executed or whether it is executed sequentially (to avoid synchronization overhead) |
---|
Binary operation on two nodes.
Parameters: |
|
---|
Shorthand for the + binop. Filters out adding 0 constants.
Shorthand for the * binop. Filters out multiplication with 1 constants.
Returns min(lhs, rhs) expression.
Note
Make lhs and rhs temporaries if they should only be evaluated once.
Index a pointer with the given index node.
Parameters: | dest_pointer_type – if given, cast the result (after adding the index) to the destination type and dereference. |
---|
Same as index(), but accepts multiple indices. This is useful e.g. after multiplication of the indices with the strides.
Create an assignment expression assigning value to node
Unary operation. type indicates the result type of the expression.
Create a constant from a Python value. If type is not given, it is inferred (or it will raise a minivect.minierror.InferTypeError).
Create a variable with a name and type. Variables may refer to function arguments, functions, etc.
Creates a node that keeps the array operand information such as the original array type, but references an actual element in the array.
Parameters: |
|
---|
Index the shape of a specific variable with integer index
Return a target that can be jumped to given a label. The label is shared between the jumpers and the target.
Raise an exception given the positional information (see the posinfo method), the exception type (PyExc_*), a formatted message string and a list of values to be used for the format string.
Return position information given a list of position variables (filename, lineno, column). This can be used for raising exceptions.
Wrap the given node, which may raise exceptions, in an error handler. An error handler allows the code to clean up before propagating the error, and finally returning an error indicator from the function.
Wrap a node and type and return a NodeWrapper node. This node will have to be handled by the caller in a code generator. The specialize_node_callback is called when the NodeWrapper is specialized by a Specializer.
Bases: minivect.miniast.ASTBuilder
Create a function with a dynamic number of arguments. This means the signature looks like
To create minivect kernels supporting this signature, set the astbuilder_cls attribute of Context to this class.
Bases: object
Each node has a position which is an instance of this type.
Bases: minivect.miniutils.ComparableObjectMixin
Base class for AST nodes.
Bases: minivect.miniast.Node
Base class for expressions. Each node has a type.
Bases: minivect.miniast.Node
Function node. error_value and success_value are returned in case of exceptions and success respectively.
the broadcast shape for all operands
the ndim of the total broadcast’ shape
all array arguments
all non-array arguments
the position variables we can write to in case of an exception
the threshold of minimum data size needed before starting a parallel section. May be overridden at any time before specialization time.
Bases: minivect.miniast.ExprNode
Call a function given a pointer or its name (FuncNameNode)
Bases: minivect.miniast.ExprNode
Load an external function by its name.
Bases: minivect.miniast.Node
Return an operand
Bases: minivect.miniast.Node
Raise a Python exception. The callee must hold the GIL.
Bases: minivect.miniast.Node
Node that holds a position of where an error occurred. This position needs to be returned to the callee if the callee supports it.
Bases: minivect.miniast.ExprNode
Argument to the FunctionNode. Array arguments contain multiple actual arguments, e.g. the data and stride pointer.
some argument to the function (array or otherwise)
the actual variables this operand should be unpacked into
Bases: minivect.miniast.ExprNode
Array operand to the function
Bases: minivect.miniast.Node
Print node for some arguments
Bases: minivect.miniast.Node
Iterate in N dimensions. See ASTBuilder.nditerate
Bases: minivect.miniast.Node
A for loop, see ASTBuilder.for_
Bases: minivect.miniast.Node
An ‘if’ statement, see A for loop, see ASTBuilder.if_
Bases: minivect.miniast.Node
A node to wrap multiple statements, see ASTBuilder.stats
Bases: minivect.miniast.Node
Turn an expression into a statement, see ASTBuilder.expr_stat
Bases: minivect.miniast.ExprNode
Adapt an opaque node to provide a consistent interface. This has to be handled by the user’s specializer. See ASTBuilder.wrap
Bases: minivect.miniast.ExprNode
Base class for binary operations
Bases: minivect.miniast.BinaryOperationNode
Node for binary operations
Bases: minivect.miniast.ExprNode
Base class for operations with one operand
Bases: minivect.miniast.ExprNode
Represents use of a function argument in the function.
Bases: minivect.miniast.Variable
Denotes an attribute of array operands, e.g. the data or stride pointers
Bases: minivect.miniast.ArrayAttribute
Reference to the start of an array operand
Bases: minivect.miniast.ArrayAttribute
Reference to the stride pointer of an array variable operand
Bases: minivect.miniast.Variable
A temporary of a certain type
Bases: minivect.miniast.Node
Execute a loop in parallel.
Bases: minivect.miniast.Node
Execute if_body if _OPENMP, otherwise execute else_body.
Bases: minivect.miniast.Node
Generate compiler-specific pragmas to aid things like SIMDization.
Bases: minivect.miniast.Node
A node to handle errors. If there is an error handler in the outer scope, the specializer will first make this error handler generate disposal code for the wrapped AST body, and then jump to the error label of the parent error handler. At the outermost (function) level, the error handler simply returns an error indication.
point to jump to in case of an error
point to jump to in the normal case
It generates the following:
error_var = 0;
...
goto cleanup;
error:
error_var = 1;
cleanup:
...
if (error_var)
goto outer_error_label;
Bases: minivect.miniast.Node
A jump to a jump target
Bases: minivect.miniast.JumpNode
A point to jump to
Bases: minivect.miniast.ExprNode
A goto label or memory address that we can jump to
Bases: minivect.miniast.ExprNode
Do nothing expression
Bases: minivect.miniast.SingleOperandNode
Load a SIMD vector
Bases: minivect.miniast.BinopNode
Store a SIMD vector
Bases: minivect.miniast.BinopNode
Binary operation on SIMD vectors
Bases: minivect.miniast.SingleOperandNode
Unary operation on SIMD vectors
Bases: minivect.miniast.ExprNode
Load the constant into the vector register
Specializers for various sorts of data layouts and memory alignments.
These specializers operate on a copy of the simplified array expression representation (i.e., one with an NDIterate node). This node is replaced with one or several ForNode nodes in a specialized order.
For auto-tuning code for tile size and OpenMP size, see https://github.com/markflorisson88/cython/blob/_array_expressions/Cython/Utility/Vector.pyx
Bases: minivect.minivisitor.VisitorTransform
Base class to map foreign ASTs onto a minivect AST, or vice-versa. This sets the current node’s position in the astbuilder for each node that is being visited, to make it easy to build new AST nodes without passing in source position information everywhere.
Bases: minivect.specializers.ASTMapper
Base class for specialization. Does not perform any specialization itself.
Allow modifications while visiting some descendant of this node This happens especially while variables are resolved, which calls compute_inner_dim_pointer()
Bases: minivect.specializers.BaseSpecializer
Base class for most specializers, provides some basic functionality for subclasses. Implement visit_* methods to specialize nodes to some pattern.
Implements implementations to handle errors and cleanups, adds a return statement to the function and can insert debug print statements if context.debug is set to a true value.
Handle a FunctionNode. Sets node.total_shape to the product of the shape, wraps the function’s body in a minivect.miniast.ErrorHandler if needed and adds a return statement.
Bases: minivect.specializers.BaseSpecializer
Perform any final specialization and optimizations. The initial specializer is concerned with specializing for the given data layouts, whereas this specializer is concerned with any rewriting of the AST to support fundamental operations.
Run any optimizations on the AST. Currently only loop-invariant code motion is implemented when broadcasting information is present.
Process variables, which includes arrays and scalars. For arrays, this means retrieving the element from the array. Performs strength reduction for index calculation of array variables.
Return the element in the array for the current index set
Same as element_location, except for Vector variables
Compute the temporary strides needed for the strength reduction. These should be small constants, so division should be fast. We could use char * instead of element_type *, but it’s nicer to avoid the casts.
Compute the data pointer for the dimension the variable is located in (the loop level). This involves generating a strength reduction in each outer dimension.
Variables referring to the same array may be found on different loop levels.
Bases: minivect.specializers.Specializer
Specializer that understands C and Fortran data layout orders.
Compute the product of the shape (entire length of array output). Sets the total shape as attribute of the function (total_shape).
Returns arguments to (x)range() to process something in C or Fortran order.
Bases: minivect.minivisitor.TreeVisitor
Determines whether we can vectorize a given expression. Currently only support arithmetic on floats and doubles.
Visits the given method if we are vectorizing, otherwise visit the superclass’ method of VectorizingSpecialization
Bases: minivect.specializers.Specializer
Generate explicitly vectorized code if supported.
Parameters: | vector_size – number of 32-bit operands in the vector |
---|
alias of CanVectorizeVisitor
Generate a loop to fix up any remaining elements that didn’t fit into our SIMD vectors.
Process an inner loop, adjusting the step accordingly and injecting any temporary assignments where necessary. Returns the fixup loop, needed when the data size is not a multiple of the vector size.
Parameters: | original_expression – original, unmodified, array expression ( the body of the NDIterate node) |
---|
Bases: minivect.specializers.OrderedSpecializer
Specialize on the first or last dimension being contiguous (depending on the ‘order’ attribute).
Bases: minivect.specializers.StridedCInnerContigSpecializer
Specialize on the first dimension being contiguous.
Bases: minivect.specializers.StridedCInnerContigSpecializer
Specialize on strided operands. If some operands are contiguous in the dimension compatible with the order we are specializing for (the first if Fortran, the last if C), then perform a direct index into a temporary date pointer. For strided operands, perform strength reduction in the inner dimension by adding the stride to the data pointer in each iteration.
Bases: minivect.specializers.StridedFortranInnerContigSpecializer, minivect.specializers.StrengthReducingStridedSpecializer
Specialize on Fortran order for strided operands and apply strength reduction in the inner dimension.
alias of StrengthReducingStridedSpecializer
Bases: minivect.specializers.OrderedSpecializer
Specialize on all specializations being contiguous (all F or all C).
Bases: minivect.specializers.StrengthReducingStridedSpecializer
Generate tiled code for the last two (C) or first two (F) dimensions. The blocksize may be overridden through the get_blocksize method, in a specializer subclass or mixin (see miniast.Context.specializer_mixin_cls).
Bases: minivect.specializers.StrengthReducingStridedFortranSpecializer, minivect.specializers.CTiledStridedSpecializer
Tile in Fortran order
Creates Vectorizing specializer classes from the given specializer for SSE and AVX.
alias of FTiledStridedSpecializer
Check for admissibility. Indicates whether partial hoisting is the most efficient thing to perform. See also partially_hoistable()
This function indicates, when admissible() returns false, whether an expression is partially hoistable. This means the caller must establish whether repeated computation or an array temporary will be more beneficial.
If the expression is a variable, there is no repeaetd computation, and it should be hoisted as far as possible.
Bases: minivect.specializers.BaseSpecializer
This transform hoists out part of sub-expressions which are broadcasting. There are two cases:
- We can hoist out the sub-expression and store it in a scalar for broadcasting
- We have to hoist the sub-expression out entirely and store it in a temporary array
As an alternative to 2), we could swap axes to return to situation 1), i.e. reorder the element-wise traversal order. We do not choose this option, since the loop order is tailored to cache-friendliness.
We determine where to hoist sub-expression to based on broadcasting information. Each type has a broadcasting tuple with a true/false value for each dimension, specifying whether it will broadcast in that dimension (i.e. broadcasting is not optional in that dimension).
We make the following observations:
Trailing truth values mean we can hoist the sub-expression out just before the first truth value in the consecutive sequence of truth values
Example (False, True, True):
A[:, None, None] * A[:, None, None] * B[:, :, :]becomes:
for i in shape[0]: temp = A[i, 0, 0] * A[i, 0, 0] for j in shape[1]: for k in shape[2]: temp * B[i, j, k]If not all consecutive leading values are false, we have to assign to a temporary array (i.e., hoist out all the way)
Example (True, True, False):
A[None, None, :] * A[None, None, :] * B[:, :, :]becomes:
allocate temp for k in shape[2]: temp[k] = A[0, 0, k] * A[0, 0, k] for i in shape[0]: for j in shape[1]: for k in shape[2]: temp[k] * B[i, j, k] deallocate temp
More generally, if the index sequence of array A is not an admissible prefix of the total index sequence, we have situation 2). For instance, (True, False, True) would mean we could hoist out the expression one level, but we would still have repeated computation. What we could do in this case, in addition to 2), is reduce indexing overhead, i.e. generate:
for j in shape[1]:
temp[j] = A[0, j, 0] * A[0, j, 0]
for i in shape[0]:
for j in shape[1]:
temp_scalar = temp[j]
for k in shape[2]:
temp_scalar * B[i, j, k]
This is bonus points.
Promote and demote values of differing types in a minivect AST. This is run before code generation. In LLVM types need to be equivalent for binary operations.
Bases: minivect.minivisitor.GenericTransform
Promote and demote values of differing types.
This module provides a minimal type system, and ways to promote types, as well as ways to convert to an LLVM type system. A set of predefined types are defined. Types may be sliced to turn them into array types, in the same way as the memoryview syntax.
>>> char
char
>>> int8[:, :, :]
int8[:, :, :]
>>> int8.signed
True
>>> uint8
uint8
>>> uint8.signed
False
>>> char.pointer()
char *
>>> int_[:, ::1]
int[:, ::1]
>>> int_[::1, :]
int[::1, :]
>>> double[:, ::1, :]
Traceback (most recent call last):
...
InvalidTypeSpecification: Step may only be provided once, and only in the first or last dimension.
Bases: minivect.minitypes.Type
Create a struct type. Fields may be ordered or unordered. Unordered fields will be ordered from big types to small types (for better alignment).
>>> struct([('a', int_), ('b', float_)], name='Foo') # ordered struct
struct Foo { int a, float b }
>>> struct(a=int_, b=float_, name='Foo') # unordered struct
struct Foo { float b, int a }
>>> struct(a=int32, b=int32, name='Foo') # unordered struct
struct Foo { int32 a, int32 b }
>>> struct(a=complex128, b=complex64, c=struct(f1=double, f2=double, f3=int32))
struct { struct { double f1, double f2, int32 f3 } c, complex128 a, complex64 b }
Adapted from Cython/Compiler/Visitor.py, see this module for detailed explanations.
Bases: object
Non-mutating visitor. Subclass and implement visit_MyNode methods. A user can traverse a foreign AST by implementing minivect.miniast.Context.getchildren
Bases: minivect.minivisitor.TreeVisitor
Mutating transform. Each attribute is replaced by the result of the corresponding visit_MyNode method.
Bases: minivect.minivisitor.TreeVisitor
Generic visitor that automatically visits children
Bases: minivect.minivisitor.VisitorTransform, minivect.minivisitor.GenericVisitor
Generic transform that automatically visits children
Bases: minivect.minivisitor.TreeVisitor
Determine whether code generated by an AST can raise exceptions.
Bases: minivect.minivisitor.TreeVisitor
Print an AST, see also minivect.miniast.Node.print_tree.
Miscellaneous (convenience) utilities.
Specialize an AST with given specializer and compile
Code generator module. Subclass CodeGen to implement a code generator as a visitor.
Bases: minivect.minivisitor.TreeVisitor
Base class for code generators written as visitors.
Bases: minivect.codegen.CodeGen
Perform cleanup for all nodes. This is invoked from an appropriate clean- up point from an minivect.miniast.ErrorHandler. Recursion should hence stop at ErrorHandler nodes, since an ErrorHandler descendant should handle its own descendants.
Users of minivect should subclass this to DECREF object temporaries, etc.
Return a printf() format specifier for the type of the given AST node
Bases: minivect.codegen.CodeGen
Generates C code from an AST, needs a minivect.minicode.CCodeWriter. To use the vectorized specializations, use the VectorCodeGen below.
Bases: minivect.codegen.CCodeGen
Generate C code for vectorized ASTs. As a subclass of CCodeGen, can write C code for any minivect AST.
Generate LLVM code for a minivect AST.
Bases: minivect.codegen.CodeGen
Generate LLVM code for a minivect AST.
Takes a regular minivect.minicode.CodeWriter to which it writes the LLVM function and a ctypes function.
OpenMP is not yet implemented, only process the ‘else’ directives.
Handle promotions as inserted by minivect.type_promoter.TypePromoter
Convert a minivect type to a ctypes type and an llvm function to a ctypes function.
Convert the minitype to a ctypes type
>>> from minitypes import *
>>> assert convert_to_ctypes(int32) == ctypes.c_int32
>>> assert convert_to_ctypes(int64) == ctypes.c_int64
>>> assert convert_to_ctypes(uint32) == ctypes.c_uint32
>>> assert convert_to_ctypes(uint64) == ctypes.c_uint64
>>> assert convert_to_ctypes(short) == ctypes.c_short
>>> assert convert_to_ctypes(int_) == ctypes.c_int
>>> assert convert_to_ctypes(long_) == ctypes.c_long
>>> assert convert_to_ctypes(float_) == ctypes.c_float
>>> assert convert_to_ctypes(double) == ctypes.c_double
>>> #convert_to_ctypes(complex64)
>>> #convert_to_ctypes(complex128)
>>> #convert_to_ctypes(complex256)
Get a ctypes function from an llvm function
Code writers and formatters. Subclass CodeWriter to suit the needs of a certain code generator backend.
Bases: object
Write code as objects for later assembly.
CodeWriter objects just before the start of each loop
same as loop_levels, but takes into account tiled loop patterns
CodeWriter objects just after the end of each loop
same as loop_levels, but a valid insertion point for C89 declarations
Bases: minivect.minicode.CodeWriter
Code writer to write C code. Has both a prototype buffer and an implementation buffer. The prototype buffer will contain the C prototypes, and the implementation buffer the actual function code.
Run the tempita template engine on string the given string.
Bases: minivect.minicode.CodeWriter
Code writer which supports writing Tempita strings. See http://pythonpaste.org/tempita/ for documentation on Tempita.
Bases: object
Default code formatting, which returns the formatted code as a list of objects (the ones written to the minivect.codegen.CodeWriter)
Bases: minivect.minicode.CodeFormatter
Format code as strings
Bases: minivect.minicode.CodeStringFormatter
Format the prototype and code implementation
Visitor to generate a Graphviz .dot file with an AST representation.
Bases: minivect.minivisitor.PrintTree
Render a minivect AST as a graphviz tree.
Convert a miniast to an XML document using ElementTree. This allows us to write XPath unit tests, or just serialize the AST.
Define some errors that may be raised by the compiler.
Bases: minivect.minierror.Error
Raised when types of values cannot be inferred
Bases: minivect.minierror.Error
Raised when a type cannot be mapped
Bases: minivect.minierror.Error
Raised when the compiler does not know how to promote two types.
Bases: minivect.minierror.Error
Raised when a type cannot be mapped to a (printf) format specifier
Bases: minivect.minierror.Error
Raised when a type is sliced incorrectly.
Bases: minivect.minierror.Error
Raised for miscellaneous errors