accelforge.frontend package#

Subpackages#

Submodules#

accelforge.frontend.arch module#

class accelforge.frontend.arch.Action[source]#

Bases: EvalableModel

An action that may be performed by a component.

energy: EvalsTo[int | float | None]#

Dynamic energy of this action. Per-action energy is multiplied by the component’s energy_scale and the action’s energy_scale.

energy_scale: EvalsTo[int | float]#

The scale factor for dynamic energy of this action. Multiplies this action’s energy by this value.

extra_attributes_for_component_model: EvalExtras#

Extra attributes to pass to the component model. In addition to all attributes of this action, any extra attributes will be passed to the component model as arguments to the component model’s action. This can be used to define attributes that are known to the component model, but not accelforge, such as clock frequency.

latency: EvalsTo[int | float | None]#

Latency of this action. Per-action latency is multiplied by the component’s latency_scale and the action’s latency_scale.

latency_scale: EvalsTo[int | float]#

The scale factor for dynamic latency of this action. Multiplies this action’s latency by this value.

name: str#

The name of this action.

class accelforge.frontend.arch.Arch[source]#

Bases: Hierarchical

Top-level architecture specification.

All attributes in the architecture can refrence variables in the spec-level variables field as well as symbols from the individual Einsum being processed.

extra_attributes_for_all_component_models: EvalExtras#

Extra attributes to pass to all component models. This can be used to pass global attributes, such as technology node or clock period, to every component model.

property per_component_total_area: dict[str, float]#

Returns the total area used by each component in the architecture in m^2.

Returns:

A dictionary of component names to their total area in m^2.

Return type:

dict[str, float]

property per_component_total_leak_power: dict[str, float]#

Returns the total leak power of each component in the architecture in W.

Returns:

A dictionary of component names to their total leak power in W.

Return type:

dict[str, float]

property total_area: float#

Returns the total area of the architecture in m^2.

Returns:

The total area of the architecture in m^2.

Return type:

float

property total_leak_power: float#

Returns the total leak power of the architecture in W.

Returns:

The total leak power of the architecture in W.

Return type:

float

variables: EvalExtras#

Like the spec-level variables field, this field is evaluated first and its contents can be referenced elsewhere in the architecture. Unlike the spec-level variables field, this, like ther rest of the architecture, is evaluated per-Einsum and can reference Einsum-specific symbols.

class accelforge.frontend.arch.ArchNode[source]#

Bases: EvalableModel

A node in the architecture.

find(name)[source]#

Finds a Leaf node with the given name.

Raises:

ValueError – If the Leaf node with the given name is not found.

Return type:

Leaf

class accelforge.frontend.arch.ArchNodes[source]#

Bases: EvalableList

A list of ArchNodes.

class accelforge.frontend.arch.Branch[source]#

Bases: ArchNode

__init__(*args, **kwargs)#

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

get_nodes_of_type(types)[source]#
Return type:

Iterator[TypeVar(T)]

nodes: ArchNodes[Annotated[Annotated[Compute, Tag(tag=Compute)] | Annotated[Memory, Tag(tag=Memory)] | Annotated[Toll, Tag(tag=Toll)] | Annotated[Fanout, Tag(tag=Fanout)] | Annotated[_Parallel, Tag(tag=_Parallel)] | Annotated[Hierarchical, Tag(tag=Hierarchical)] | Annotated[Fork, Tag(tag=Fork)], Discriminator(discriminator=_get_tag, custom_error_type=None, custom_error_message=None, custom_error_context=None)]]#
class accelforge.frontend.arch.Comparison[source]#

Bases: EvalableModel

A comparison between a rank variable’s bound and a value. A comparison is performed for each rank variable.

The LHS of each comparison is the loop bound of a loop that affects this rank variable. The RHS is the given value.

For example, if the expression resolves to [a, b], the operator is “<=”, and the value is 10, and we have loops “for a0 in [0..A0)” and “for b0 in [0..B0)”, then a mapping is only valid if A0 <= 10 and B0 <= 10.

expression: TryEvalTo[InvertibleSet[str]]#

The expression to compare. This expression should resolve to a set of rank variables. A comparison is performed for each rank variable independently, and the result passes if and only if all comparisons pass. The LHS of each comparison is the loop bound of a loop that affects this rank variable. The RHS is the given value.

operator: str#

The operator to use for the comparison. Supported operators are: - == (equal to) - <= (less than or equal to) - >= (greater than or equal to) - < (less than) - > (greater than) - product== (product of all loop bounds is equal to) - product<= (product of all loop bounds is less than or equal to) - product>= (product of all loop bounds is greater than or equal to) - product< (product of all loop bounds is less than) - product> (product of all loop bounds is greater than)

value: EvalsTo[int]#

The value to compare against.

class accelforge.frontend.arch.Component[source]#

Bases: Leaf

A component object in the architecture. This is overridden by different component types, such as Memory and Compute.

__init__(*args, **kwargs)#

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

actions: EvalableList[Action]#

The actions that this Component can perform.

area: EvalsTo[int | float | None]#

The area of a single instance of this component in m^2. If set, area calculations will use this value.

area_scale: EvalsTo[int | float]#

The scale factor for the area of this comxponent. This is used to scale the area of this component. For example, if the area is 1 m^2 and the scale factor is 2, then the area is 2 m^2.

calculate_action_energy(component_models=None, in_place=False)[source]#

Calculates energy for each action of this component. If energy is set in the action or component (with action taking precedence), that value will be used. Otherwise, the energy will be calculated using hwcomponents. Populates, for each action, the <action>.energy and field. Extends the component_modeling_log field with log messages.

Uses the component_model attribute, or, if not set, the component_class attribute to find the model and populate the component_model attribute.

Note that these methods will be called by the Spec when calculating energy and area. If you call them yourself, note that string expressions may not be evaluated because they need the Spec’s global scope. If you are sure that all necessary values are present and not a result of an expression, you can call these directly. Otherwise, you can call the Spec.calculate_component_area_energy_latency_leak and then grab components from the returned Spec.

Parameters:
  • component_models (list[hwcomponents.ComponentModel] | None) – The models to use for energy calculation. If not provided, the models will be found with hwcomponents.get_models().

  • in_place (bool) – If True, the component will be modified in place. Otherwise, a copy will be returned.

Returns:

A copy of the component with the calculated energy.

Return type:

T

calculate_action_latency(component_models=None, in_place=False)[source]#

Calculates the latency for each action by this component. Populates the <action>.latency field. Extends the component_modeling_log field with log messages.

Parameters:
  • component_models (list[hwcomponents.ComponentModel] | None) – The models to use for latency calculation. If not provided, the models will be found with hwcomponents.get_models().

  • in_place (bool) – If True, the component will be modified in place. Otherwise, a copy will be returned.

Returns:

A copy of the component with the calculated latency for each action.

Return type:

Self

calculate_area(component_models=None, in_place=False)[source]#

Calculates the area for this component. If area is set in the component, that value will be used. Otherwise, the area will be calculated using the hwcomponents library. Populates area field. Extends the component_modeling_log field with log messages.

Uses the component_model attribute, or, if not set, the component_class attribute to find the model and populate the component_model attribute.

Note that these methods will be called by the Spec when calculating energy and area. If you call them yourself, note that string expressions may not be evaluated because they need the Spec’s global scope. If you are sure that all necessary values are present and not a result of an expression, you can call these directly. Otherwise, you can call the Spec.calculate_component_area_energy_latency_leak and then grab components from the returned Spec.

Parameters:
  • component_models (list[hwcomponents.ComponentModel] | None) – The models to use for area calculation. If not provided, the models will be found with hwcomponents.get_models().

  • in_place (bool) – If True, the component will be modified in place. Otherwise, a copy will be returned.

Returns:

A copy of the component with the calculated area.

Return type:

Self

calculate_area_energy_latency_leak(component_models=None, in_place=False, _use_cache=False)[source]#

Calculates the area, energy, latency, and leak power for this component. Populates the area, total_area, leak_power, total_leak_power, total_latency, and component_modeling_log fields of this component. Additionally, for each action, populates the <action>.area, <action>.energy, <action>.latency, and <action>.leak_power fields. Extends the component_modeling_log field with log messages.

Note that these methods will be called by the Spec when calculating energy and area. If you call them yourself, note that string expressions may not be evaluated because they need the Spec’s global scope. If you are sure that all necessary values are present and not a result of an expression, you can call these directly. Otherwise, you can call the Spec.calculate_component_area_energy_latency_leak and then grab components from the returned Spec.

Parameters:
  • component_models (list[hwcomponents.ComponentModel] | None) – The models to use for energy calculation. If not provided, the models will be found with hwcomponents.get_models().

  • in_place (bool) – If True, the component will be modified in place. Otherwise, a copy will be returned.

  • _use_cache (bool) – If True, the component model will be cached and reused if the same component class, attributes, and actions are provided. Note that this may return copies of the same object across multiple calls.

Returns:

The component with the calculated energy, area, and leak power.

Return type:

Self

calculate_leak_power(component_models=None, in_place=False)[source]#

Calculates the leak power for this component. If leak power is set in the component, that value will be used. Otherwise, the leak power will be calculated using hwcomponents. Populates leak_power field. Extends the component_modeling_log field with log messages.

Uses the component_model attribute, or, if not set, the component_class attribute to find the model and populate the component_model attribute.

Note that these methods will be called by the Spec when calculating energy and area. If you call them yourself, note that string expressions may not be evaluated because they need the Spec’s global scope. If you are sure that all necessary values are present and not a result of an expression, you can call these directly. Otherwise, you can call the Spec.calculate_component_area_energy_latency_leak and then grab components from the returned Spec.

Parameters:
  • component_models (list[hwcomponents.ComponentModel] | None) – The models to use for energy calculation. If not provided, the models will be found with hwcomponents.get_models().

  • in_place (bool) – If True, the component will be modified in place. Otherwise, a copy will be returned.

Returns:

A copy of the component with the calculated energy.

Return type:

Self

component_class: str | None#

The class of this Component. Used if an energy or area model needs to be called for this Component.

component_model: ComponentModel | None#

The model to use for this Component. If not set, the model will be found with hwcomponents.get_models(). If set, the component_class will be ignored.

component_modeling_log: list[str]#

A log of the energy and area calculations for this Component.

enabled: TryEvalTo[bool]#

Whether this component is enabled. If the expression resolves to False, then the component is disabled. This is evaluated per-pmapping-template, so it is a function of the tensors in the current Einsum. For example, you may say len(All) >= 3 and the component will only be enabled with Einsums with three or more tensors.

energy_scale: EvalsTo[int | float]#

The scale factor for dynamic energy of this component. For each action, multiplies this action’s energy. Multiplies the calculated energy of each action.

extra_attributes_for_component_model: _ExtraAttrs#

Extra attributes to pass to the component model. In addition to all attributes of this component, any extra attributes will be passed to the component model. This can be used to define attributes that are known to the component model, but not accelforge, such as the technology node.

get_component_class(trying_to_calculate=None)[source]#

Returns the class of this Component.

Parameters:

trying_toeval (str, optional) – What was trying to be calculated using this component. If provided, the error message will be more specific.

Raises:

EvaluationError – If the component_class is not set.

Return type:

str

latency_scale: EvalsTo[int | float]#

The scale factor for the latency of this component. This is used to scale the latency of this component. For example, if the latency is 1 ns and the scale factor is 2, then the latency is 2 ns. Multiplies the calculated latency of each action.

leak_power: EvalsTo[int | float | None]#

The leak power of a single instance of this component in W. If set, leak power calculations will use this value.

leak_power_scale: EvalsTo[int | float]#

The scale factor for the leak power of this component. This is used to scale the leak power of this component. For example, if the leak power is 1 W and the scale factor is 2, then the leak power is 2 W.

n_parallel_instances: EvalsTo[int | float]#

The number of parallel instances of this component. Increasing parallel instances will proportionally increase area and leakage, while reducing latency (unless latency calculation is overridden).

name: str#

The name of this Component.

populate_component_model(component_models=None, in_place=False, trying_to_calculate=None)[source]#

Populates the component_model attribute with the model for this component. Extends the component_modeling_log field with log messages. Uses the component_class attribute to find the model and populate the component_model attribute. Uses the hwcomponents.get_model() function to find the model.

Parameters:
  • component_models (list[hwcomponents.ComponentModel] | None) – The models to use for energy calculation. If not provided, the models will be found with hwcomponents.get_models().

  • in_place (bool) – If True, the component will be modified in place. Otherwise, a copy will be returned.

  • trying_to_calculate (str, optional) – What was trying to be calculated using this component. If provided, the error messages for missing component_class will be more specific.

Returns:

A copy of the component with the populated component_model attribute.

Return type:

T

total_area: EvalsTo[int | float | None]#

The total area of all instances of this component in m^2. Do not set this value. It is calculated when the architecture’s area is calculated.

total_latency: str | int | float#

An expression representing the total latency of this component in seconds. This is used to calculate the latency of a given Einsum. Special variables available are the following:

  • min: The minimum value of all arguments to the expression.

  • max: The maximum value of all arguments to the expression.

  • sum: The sum of all arguments to the expression.

  • X_actions: The number of times action X is performed. For example, read_actions is the number of times the read action is performed.

  • X_latency: The total latency of all actions of type X. For example, read_latency is the total latency of all read actions. It is equal to the per-read latency multiplied by the number of read actions.

  • action2latency: A dictionary of action names to their latency.

Additionally, all component attributes are availble as variables, and all other functions generally available in parsing. Note this expression is evaluated after other component attributes are evaluated.

For example, the following expression calculates latency assuming that each read or write action takes 1ns: 1e-9 * (read_actions + write_actions).

total_leak_power: EvalsTo[int | float | None]#

The total leak power of all instances of this component in W. Do not set this value. It is calculated when the architecture’s leak power is calculated. If instances are power gated, actual leak power may be less than this value.

class accelforge.frontend.arch.Compute[source]#

Bases: Component

actions: EvalableList[Action]#

The actions that this Compute can perform.

class accelforge.frontend.arch.Fanout[source]#

Bases: Leaf

Creates a spatial fanout, and doesn’t do anything else.

class accelforge.frontend.arch.Fork[source]#

Bases: Hierarchical

A Fork is a Hierarchical that branches off from the main path. The nodes inside the Fork are a separate branch, while the main path continues to the next sibling after the Fork.

class accelforge.frontend.arch.Hierarchical[source]#

Bases: Branch

render()[source]#

Renders the architecture as a Pydot graph.

Return type:

str

class accelforge.frontend.arch.Leaf[source]#

Bases: ArchNode

A leaf node in the architecture. This is an abstract class that represents any node that is not a Branch.

__init__(*args, **kwargs)#

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

get_fanout()[source]#

The spatial fanout of this node.

Return type:

int

name: str#

The name of this Leaf.

spatial: EvalableList[Spatial]#

The spatial fanouts of this Leaf.

Spatial fanouts describe the spatial organization of components in the architecture. A spatial fanout of size N for this node means that there are N instances of this node. Multiple spatial fanouts lead to a multi-dimensional fanout. Spatial constraints apply to the data exchange across these instances. Spatial fanouts specified at this level also apply to lower-level Leaf nodes in the architecture.

class accelforge.frontend.arch.Memory[source]#

Bases: TensorHolder

A Memory is a TensorHolder that stores data over time, allowing for temporal reuse.

actions: EvalableList[TensorHolderAction]#

The actions that this Memory can perform.

size: EvalsTo[int | float]#

The size of this Memory in bits.

class accelforge.frontend.arch.Spatial[source]#

Bases: EvalableModel

A one-dimensional spatial fanout in the architecture.

fanout: EvalsTo[int]#

The size of this fanout.

loop_bounds: EvalableList[Comparison]#

Bounds for loops over this dimension. This is a list of Comparison objects, all of which must be satisfied by the loops to which this constraint applies.

Note: Loops may be removed if they are constrained to only one iteration.

may_reuse: TryEvalTo[InvertibleSet[str]]#

The tensors that can be reused spatially across instances of this fanout. This expression will be evaluated for each mapping template.

min_usage: int | float | str#

The minimum usage of spatial instances, as a value from 0 to 1. A mapping is invalid if less than this porportion of this dimension’s fanout is utilized. Mappers that support it (e.g., FFM) may, if no mappings satisfy this constraint, return the highest-usage mappings.

name: str#

The name of the dimension over which this spatial fanout is occurring (e.g., X or Y).

power_gateable: EvalsTo[bool]#

Whether this spatial fanout has power gating. If True, then unused spatial instances will be power gated if not used by a particular Einsum.

reuse: TryEvalTo[InvertibleSet[str]]#

A set of tensors or a set expression representing tensors that must be reused across spatial iterations. Spatial loops may only be placed that reuse ALL tensors given here.

Note: Loops may be removed if they do not reuse a tensor given here and they do not appear in another loop bound constraint.

usage_scale: EvalsTo[int | float | str]#

This factor scales the usage in this dimension. For example, if usage_scale is 2 and 10/20 spatial instances are used, then the usage will be scaled to 20/20.

class accelforge.frontend.arch.TensorHolder[source]#

Bases: Component

A TensorHolder is a component that holds tensors. These are usually Memories, but can also be Tolls.

__init__(*args, **kwargs)#

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

actions: EvalableList[TensorHolderAction]#

The actions that this TensorHolder can perform.

bits_per_action: EvalsTo[int | float | None]#

The number of bits accessed in each of this component’s actions. Overridden by bits_per_action in any action of this component. If set here, acts as a default value for the bits_per_action of all actions of this component.

bits_per_value_scale: EvalsTo[dict]#

A scaling factor for the bits per value of the tensors in this TensorHolder. If this is a dictionary, keys in the dictionary are evaluated as expressions and may reference one or more tensors.

tensors: Tensors#

Fields that control which tensor(s) are kept in this TensorHolder and in what order their nodes may appear in the mapping.

class accelforge.frontend.arch.TensorHolderAction[source]#

Bases: Action

bits_per_action: EvalsTo[int | float]#

The number of bits accessed in this action. For example, setting bits_per_action to 16 means that each call to this action yields 16 bits.

class accelforge.frontend.arch.Tensors[source]#

Bases: EvalableModel

Fields that control which tensor(s) are kept in a TensorHolder and in what order their nodes may appear in the mapping.

back: TryEvalTo[InvertibleSet[str]]#

A set expression describing which tensors must be backed by this accelforge.frontend.arch.TensorHolder. If this is not defined, then no tensors must be backed.

force_memory_hierarchy_order: bool#

If set to true, storage nodes for lower-level memories must be placed below storage nodes for higher-level memories. For example, all MainMemory storage nodes must go above all LocalBuffer storage nodes.

This constraint always applies to same-tensor storage nodes (e.g., MainMemory reusing Output must go above LocalBuffer reusing Output); turning it off will permit things like MainMemory reusing Output going above LocalBuffer reusing Input.

This is identical to the force_memory_hierarchy_order field in the FFM class, but only applies to this tensor holder.

keep: TryEvalTo[InvertibleSet[str]]#

A set expression describing which tensors must be kept in this accelforge.frontend.arch.TensorHolder. If this is not defined, then all tensors must be kept. Any tensors that are in back will also be added to keep.

may_keep: TryEvalTo[InvertibleSet[str]]#

A set expression describing which tensors may optionally be kept in this accelforge.frontend.arch.TensorHolder. The mapper will explore both keeping and not keeping each of these tensors. If this is not defined, then all tensors may be kept.

no_refetch_from_above: TryEvalTo[InvertibleSet[str]]#

The tensors that are not allowed to be refetched from above. This is given as a set of TensorName objects or a set expression that resolves to them. These tensors must be fetched at most one time from above memories, and may not be refetched across any temporal or spatial loop iterations. Tensors may be fetched in pieces (if they do not cause re-fetches of any piece).

tensor_order_options: EvalableList[EvalableList[TryEvalTo[InvertibleSet[str]]]]#

Options for the order of tensor storage nodes in the mapping. This is given as a list-of-lists-of-sets. Each list-of-sets is a valid order of tensor storage nodes. Order is given from highest in the mapping to lowest.

For example, an option could be [input | output, weight], which means that there is no relative ordering required between input and output, but weight must be below both.

tile_shape: EvalableList[Comparison]#

The tile shape for each rank variable. This is given as a list of Comparison objects, where each comparison must evaluate to True for a valid mapping.

class accelforge.frontend.arch.Toll[source]#

Bases: TensorHolder

A Toll is a TensorHolder that does not store data over time, and therefore does not allow for temporal reuse. Use this as a toll that charges reads and writes every time a piece of data moves through it.

Every write to a Toll is immediately written to the next Memory (which may be above or below depending on where the write came from), and same for reads.

The access counts of a Toll are only included in the “read” action. Each traversal through the Toll is counted as a read. Writes are always zero.

actions: EvalableList[TensorHolderAction]#

The actions that this Toll can perform.

direction: Literal['up', 'down', 'up_and_down']#

The direction in which data flows through this Toll. If “up”, then data flows from below TensorHolder, through this Toll (plus paying associated costs), and then to the next TensorHolder above it. Other data movements are assumed to avoid this Toll.

accelforge.frontend.config module#

class accelforge.frontend.config.Config[source]#

Bases: EvalableModel

component_models: EvalableList[str | ComponentModel]#

A list of hwcomponents models to use for the energy and area calculations. These can either be paths to Python files that contain the models, or hwcomponents ComponentModel objects.

expression_custom_functions: EvalableList[str | Callable]#

A list of functions to use while parsing expressions. These can either be functions or paths to Python files that contain the functions. If a path is provided, then all functions in the file will be added to the evaluator.

classmethod from_yaml(f)[source]#

Loads a dictionary from one more more yaml files.

Each yaml file should contain a dictionary. Dictionaries are combined in the order they are given.

Keyword arguments are also added to the dictionary.

Parameters:
  • files – A list of yaml files to load.

  • jinja_parse_data – Optional[Dict[str, Any]] A dictionary of Jinja2 data to use when parsing the yaml files.

  • top_key – Optional[str] The top key to use when parsing the yaml files.

  • kwargs – Extra keyword arguments to be passed to the constructor.

Return type:

Config

Returns:

A dict containing the combined dictionaries.

use_installed_component_models: bool | None#

If True, then the hwcomponents library will find all installed models. If False, then only the models specified in component_models will be used.

accelforge.frontend.config.get_config()[source]#
Return type:

Config

accelforge.frontend.model module#

class accelforge.frontend.model.Model[source]#

Bases: EvalableModel

Configuration for the model.

metrics: Metrics#

Metrics to evaluate.

If using spec to call mapper, leave this configuration as is. The mapper will make necessary configurations.

accelforge.frontend.renames module#

class accelforge.frontend.renames.EinsumRename[source]#

Bases: EvalableModel

Renames for a single Einsum.

__init__(*args, **kwargs)[source]#

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

name: str#

The name of the Einsum. Set this to “default” to apply the renames to all Einsums, unless overridden. Overriding is specific to a single name, so every rename in the default must be overridden independently.

rank_variables: EvalableList[Rename]#

Renames for the rank variables of this Einsum. This may be given either as a dictionary {new_name: source_set_expression} expressions, or as a list of dictionaries, each one having the structure {name: new_name, source: source_set_expression, expected_count: 1}, where expected count is optional for each and may be set to any integer.

tensor_accesses: EvalableList[Rename]#

Renames for the tensor accesses of this Einsum. This may be given either as a dictionary {new_name: source_set_expression} expressions, or as a list of dictionaries, each one having the structure {name: new_name, source: source_set_expression, expected_count: 1}, where expected count is optional for each and may be set to any integer.

class accelforge.frontend.renames.Rename[source]#

Bases: EvalableModel

A rename of something into something else.

expected_count: EvalsTo[int] | None#

The expected count of the source set expression. If this is set, then the source expression must resolve to the expected count or an error will be raised. Otherwise, any count (including zero for an empty set) is allowed.

name: str#

The name of the thing to be renamed. This is a string representing the new name.

source: TryEvalTo[InvertibleSet[str]]#

The source of the rename. This is a set expression that can be evaluated, yielding a set that can be referenced by the new name.

class accelforge.frontend.renames.RenameList[source]#

Bases: EvalableList[Rename]

A list of renames.

class accelforge.frontend.renames.Renames[source]#

Bases: EvalableModel

einsums: list[EinsumRename]#

Renames for a workload. The Einsum list is a list of EinsumRename objects, and renames will be applied to Einsums whose names match the EinsumRename.name. If an EinsumRename is named “default”, then its renames are applied to every Einsum unless overridden. Overriding is specific to a single name, so every rename in the default must be overridden independently.

get_renames_for_einsum(einsum_name)[source]#
Return type:

EinsumRename

accelforge.frontend.renames.rename_list_factory(rename_list)[source]#
Return type:

RenameList

accelforge.frontend.spec module#

class accelforge.frontend.spec.Spec[source]#

Bases: EvalableModel

The top-level spec of all of the inputs to this package.

arch: Arch#

The hardware architecture being used.

calculate_component_area_energy_latency_leak(einsum_name=None, area=True, energy=True, latency=True, leak=True)[source]#

Populates per-component area, energy, latency, and/or leak power. For each component, populates the area, total_area, leak_power and total_leak_power. Additionally, for each action of each component, populates the <action>.energy and <action>.latency fields. Extends the component_modeling_log field with log messages. Also populates the component_model attribute for each component if not already set.

Some architectures’ attributes may depend on the workload. In that case, an Einsum name can be provided to populate those symbols with the Einsum’s symbols from the workload.

Parameters:
  • einsum_name (EinsumName | None = None) – Optional Einsum name to populate symbols with the Einsum’s symbols from the workload. If None, and there are Einsums in the workload, the first Einsum is used. If None and there are no Einsums in the workload, then no symbols are populated from the workload.

  • area (bool, optional) – Whether to compute and populate area entries.

  • energy (bool, optional) – Whether to compute and populate energy entries.

  • latency (bool, optional) – Whether to compute and populate latency entries.

  • leak (bool, optional) – Whether to compute and populate leak power entries.

Return type:

Spec

config: Config#

Configuration settings.

map_workload_to_arch(einsum_names=None, print_number_of_pmappings=True, _pmapping_row_filter_function=None)[source]#

Maps the workload to the architecture using the AccelForge Fast and Fusiest Mapper (FFM).

Parameters:
  • spec – The Spec to map.

  • einsum_names (list[str] | None) – The einsum names to map. If None, all einsums will be mapped.

  • can_combine_multiple_runs (Whether we would like to be able to combine multiple) – make_pmappings runs. Having this as True allows you to do things like pmappings = make_pmappings(*args_a) | make_pmappings(*args_b) but slows down execution.

  • cache_dir – The directory to cache pmappings in. If None, no caching will be done.

  • print_number_of_pmappings (bool) – Whether to print the number of pmappings for each einsum.

  • _pmapping_row_filter_function (Optional[Callable[[Series], bool]]) – A function that takes in a row of the pmapping dataframe and returns True if the row should be included in the final mappings, and False otherwise. If None, all rows will be included.

Returns:

The mappings of the workload to the architecture.

Return type:

Mappings

mapper: FFM#

Configures the mapper used to map the workload onto the architecture.

mapping: Mapping#

How the workload is programmed onto the architecture. Do not specify this if you’d like the mapper to generate a mapping for you.

model: Model#

Configures the model used to evaluate mappings.

renames: Renames#

Aliases for tensors in the workload so that they can be called by canonical names when writing architecture constraints. For example, workload tensors may be renamed to “input”, “output”, and “weight”.

variables: Variables#

Variables that can be referenced in other places in the spec.

workload: Workload#

The program to be run on the arch.

accelforge.frontend.spec.Specification#

alias of Spec

accelforge.frontend.variables module#

class accelforge.frontend.variables.Variables[source]#

Bases: EvalExtras

Variables that can be used in parsing. All variables defined here can be referenced elsewhere in any of the Spec’s evaluated expressions.

accelforge.frontend.workload module#

All the objects used for a Workload description in AccelForge.

class accelforge.frontend.workload.Einsum[source]#

Bases: EvalableModel

Represents an Einsum, which is a single computation step in the workload. The Einsum includes a set of rank variables, which are used to index into tensors. Rank variables iterate through an iteration space.

For example, if the Einsum is A[m, n] += B[k, n] * C[k, n] and we define the iteration space as “0 <= m < 10, 0 <= n < 10, 0 <= k < 10”, then the Einsum will iterate through all possible values of (m, n, k) in the iteration space, indexing into tensors for each and updating A[m, n] with B[k, n] * C[k, n].

__init__(*args, **kwargs)[source]#

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

copy_source_tensor()[source]#

If this Einsum is a copy operation, returns the name of the tensor that is the source of the copy. Otherwise, returns None.

Return type:

str | None

static empty_renames()[source]#
Return type:

dict[str, InvertibleSet[str]]

property indexing_expressions: set[str]#

Returns a list of all the expressions that index into the tensors of this Einsum.

property input_tensor_names: set[str]#

Returns the names of the input tensors of this Einsum.

is_copy_operation: bool#

Whether the Einsum is a copy operation. Copy operations take the input tensor and directly place them at the location of the output tensor(s) without any computation. If the destination tensor is at the same location, then this is a no-op.

iteration_space_shape: Shape[str]#

Bounds of valid rank variable values. This is a list of expressions, each one an ISL expression. Additionally, global iteration_space_shape expressions are appended to the list if their rank variables are present in the Einsum’s rank_variables. For example, if the global scope has “m: 0 <= m < 10” and the Einsum has “m” in its rank_variables, then “0 <= m < 10” will be appended to the iteration_space_shape.

n_instances: int#

Number of times to repeat the Einsum. Multiplied by Workload.n_instances to get the total number of Einsum instances. Energy, latency, and other summable metrics are multiplied by this value. Persistent reservations are also multiplied by this value, but non-persistent reservations are not, as they are assumed to be freed between each instance.

name: str#

The name of the Einsum.

property output_tensor_names: set[str]#

Returns the names of the output tensors of this Einsum.

rank_sizes: EvalableDict[str, int]#

Sizes of ranks. This is a dictionary of rank names to sizes. Sizes are integers, and the rank’s bounds are 0 <= rank < size. Accesses outside of these bounds are skipped.

property rank_variable2ranks: dict[str, set[str]]#

Returns a dictionary of rank variables to the ranks that are indexed into by that rank variable.

property rank_variables: set[str]#

Returns all rank variables used in this Einsum.

property ranks: set[str]#

Returns all ranks used in this Einsum.

renames: RenameList[Rename]#

Renames of the Einsum. Renames here can be used to rename rank variables or tensors. When this Einsum is executed on an architecture, the architecture can use renamed tensors and rank variables to access the tensors and rank variables.

property tensor2directly_indexing_rank_variables: dict[str, set[str]]#

Returns a dictionary of tensor names to the rank variables that directly index into that tensor. Direct indexing means that the rank variable is used as a direct index into the tensor, without any expression (e.g., “M=m”, NOT “M=m+n”).

property tensor2expression_indexing_rank_variables: dict[str, set[str]]#

Returns a dictionary of tensor names to the rank variables that indirectly index into that tensor through an expression (e.g., “M=m+n”) instead of a direct index (e.g., “M=m”).

property tensor2irrelevant_rank_variables: dict[str, set[str]]#

Returns a dictionary of tensor names to the rank variables that are irrelevant to that tensor. Irrelevant rank variables are rank variables that are not used to index into the tensor.

property tensor2rank_variables: dict[str, set[str]]#

Returns a dictionary of tensor names to the rank variables that project into that tensor.

tensor_accesses: EvalableList[TensorAccess]#

The tensors accessed by this Einsum, and how they are accessed.

property tensor_names: set[str]#

Returns the names of all tensors of this Einsum.

class accelforge.frontend.workload.ImpliedProjection[source]#

Bases: dict

Holds a projection that has been implied by a list of rank variables. The implied rank names are uppercased versions of the rank variables; for example, [a, b, c] -> {A: a, B: b, C: c}.

class accelforge.frontend.workload.Shape[source]#

Bases: EvalableList

Specifies valid values for the rank variables. This is a list of strings, each one an ISL expression. The total space is considered to be the logal AND of all the expressions in the list.

property rank_variables: set[str]#

Returns all rank variables used in this shape.

class accelforge.frontend.workload.TensorAccess[source]#

Bases: EvalableModel

Information about how an Einsum accesses a tensor.

backing_storage_size_scale: float#

If != 1, then the backing storage size will be scaled by this factor.

bits_per_value: int | str | None#

Bits per value for this tensor.

property directly_indexing_rank_variables: set[str]#

Returns the rank variables that directly index into this tensor without any expression (e.g., “M=m”, NOT “M=m+n”).

property expression_indexing_rank_variables: set[str]#

Returns the rank variables that indirectly index into this tensor through an expression (e.g., “M=m+n”) instead of a direct index (e.g., “M=m”).

name: str#

The name of the tensor.

output: bool#

Whether the tensor is an output. False means the tensor is an input.

persistent: bool#

If True, then a copy of this tensor must remain in backing storage for the full duration of the workload’s execution.

projection: dict[str, str] | list[str]#

How the rank variables of the Einsum project into the tensor. If this is a list, then it is assumed that each of the elements of the list is a single rank variable and they index into the tensor in ranks that equal the uppercase of the rank variable. For example:

name: X, projection: [a, b, c] means X[A=a, B=b, C=c]

If this is a dictionary, it is a mapping from rank names to rank variable expressions. This can be used to either project into a non-matching rank name or to project into a tensor using an expression. For example:

name: X, projection: {A: a, B2: b, C: a+b} means X[A=a, B2=b, C=a+b]

property rank2rank_variables: dict[str, set[str]]#

Returns a dictionary of rank names to the rank variables that project into that rank.

property rank_variable2ranks: dict[str, set[str]]#

Returns a dictionary of rank variables to the ranks into which that rank variable projects.

property rank_variables: set[str]#

Returns all rank variables used in this access.

property ranks: tuple[str, ...]#

Returns the ranks of this access’s tensor.

class accelforge.frontend.workload.Workload[source]#

Bases: EvalableModel

The workload specification as a cascade of Einsums, with each Einsum being a computation step in the workload.

accesses_for_tensor(tensor)[source]#

Returns all TensorAccess objects that access the given tensor across all Einsums.

Parameters:

tensor (TensorName) – The tensor to check.

Returns:

The TensorAccess objects that access the given tensor across all Einsums. Order is the same as the order in this workload’s Einsums list.

Return type:

list[TensorAccess]

bits_per_value: EvalableDict[str, int | str]#

Bits per value for each tensor. The workload-level bits_per_value is overridden if bits_per_action is specified for any given tensor access. This is a dictionary of set expressions to bits per value for the tensors given by those expressions. For example, we may write “Inputs: 8” to set the bits per value to 8 for all input tensors, unless overridden.

property einsum_names: list[str]#

Returns the names of the Einsums in the workload.

einsums: EvalableList[Einsum]#

The Einsums in the workload.

einsums_with_tensor(tensor)[source]#

Returns the Einsums in the workload that access the given tensor.

Parameters:

tensor (TensorName) – The tensor to check.

Returns:

The Einsums in the workload that access the given tensor. Order is the same as the order in this workload’s Einsums list.

Return type:

list[Einsum]

einsums_with_tensor_as_input(tensor)[source]#

Returns the Einsums in the workload that use the given tensor as an input.

Parameters:

tensor (TensorName) – The tensor to check.

Returns:

The Einsums in the workload that use the given tensor as an input. Order is the same as the order in this workload’s Einsums list.

Return type:

list[Einsum]

einsums_with_tensor_as_output(tensor)[source]#

Returns the Einsums in the workload that have the given tensor as an output.

Parameters:

tensor (TensorName) – The tensor to check.

Returns:

The Einsums in the workload that have the given tensor as an output. Order is the same as the order in this workload’s Einsums list.

Return type:

list[Einsum]

empty_renames()[source]#
Return type:

dict[str, InvertibleSet[str]]

get_iteration_space_shape_isl_string(einsum_name)[source]#

Returns the ISL string representing the iteration space of the given Einsum.

Parameters:

einsum_name (str) – The name of the Einsum for which to get the iteration space shape.

Returns:

The ISL string representing the iteration space shape of the given Einsum.

Return type:

str

get_tensor_copies()[source]#

Returns a dictionary specifying which tensors are copies of which other tensors. For example, if einsum A copies tensor X into tensors Y and Z, then we’d have in the return value X: {Y, Z}, Y: {X, Z}, and Z: {X, Y}. This is transitive.

Returns:

A dictionary specifying which tensors are copies of which other tensors. The keys are the tensors that are copies, and the values are sets of tensors that are copies of the key.

Return type:

dict[TensorName, set[TensorName]]

iteration_space_shape: EvalableDict[str, str]#

Bounds of valid rank variable values. This is a dictionary of rank variable names to bounds of valid rank variable values. The bounds are specified as a string in the ISL format. For example, “0 <= a < 10” means that the rank variable a must be between 0 and 10, including 0 but not 10. Bounds are included for all Einsums that include that rank variable.

n_instances: int#

Number of times to repeat the workload. Multiplied by Einsum.n_instances to get the total number of Einsum instances. Energy, latency, and other summable metrics are multiplied by this value. Persistent reservations are also multiplied by this value, but non-persistent reservations are not, as they are assumed to be freed between each instance.

rank_sizes: EvalableDict[str, EvalsTo[int]]#

Rank sizes. This is a dictionary of rank names to sizes. Sizes are integers, and the rank’s bounds are 0 <= rank < size. Accesses outside of these bounds are skipped.

property rank_variables: set[str]#

Returns the names of all rank variables in the workload.

render()[source]#

Renders the workload as a Pydot graph. Returns an SVG string.

Return type:

str

property tensor_names: set[str]#

Returns the names of all tensors in the workload.

property tensor_names_used_in_multiple_einsums: set[str]#

Returns the names of the tensors that are used in multiple Einsums.

accelforge.frontend.workload.isl_expression_has_variable(expression, variable)[source]#

Returns True if the given ISL expression has the given rank variable.

Parameters:
  • expression (str) – The ISL expression to check.

  • variable (RankVariable) – The rank variable to check for.

Returns:

True if the given ISL expression has the given rank variable.

Return type:

bool

Module contents#

Timeloop Spec. Each piece below (minus processors) corresponds to a top key in the Timeloop spec.

class accelforge.frontend.Spec[source]#

Bases: EvalableModel

The top-level spec of all of the inputs to this package.

arch: Arch#

The hardware architecture being used.

calculate_component_area_energy_latency_leak(einsum_name=None, area=True, energy=True, latency=True, leak=True)[source]#

Populates per-component area, energy, latency, and/or leak power. For each component, populates the area, total_area, leak_power and total_leak_power. Additionally, for each action of each component, populates the <action>.energy and <action>.latency fields. Extends the component_modeling_log field with log messages. Also populates the component_model attribute for each component if not already set.

Some architectures’ attributes may depend on the workload. In that case, an Einsum name can be provided to populate those symbols with the Einsum’s symbols from the workload.

Parameters:
  • einsum_name (EinsumName | None = None) – Optional Einsum name to populate symbols with the Einsum’s symbols from the workload. If None, and there are Einsums in the workload, the first Einsum is used. If None and there are no Einsums in the workload, then no symbols are populated from the workload.

  • area (bool, optional) – Whether to compute and populate area entries.

  • energy (bool, optional) – Whether to compute and populate energy entries.

  • latency (bool, optional) – Whether to compute and populate latency entries.

  • leak (bool, optional) – Whether to compute and populate leak power entries.

Return type:

Spec

config: Config#

Configuration settings.

map_workload_to_arch(einsum_names=None, print_number_of_pmappings=True, _pmapping_row_filter_function=None)[source]#

Maps the workload to the architecture using the AccelForge Fast and Fusiest Mapper (FFM).

Parameters:
  • spec – The Spec to map.

  • einsum_names (list[str] | None) – The einsum names to map. If None, all einsums will be mapped.

  • can_combine_multiple_runs (Whether we would like to be able to combine multiple) – make_pmappings runs. Having this as True allows you to do things like pmappings = make_pmappings(*args_a) | make_pmappings(*args_b) but slows down execution.

  • cache_dir – The directory to cache pmappings in. If None, no caching will be done.

  • print_number_of_pmappings (bool) – Whether to print the number of pmappings for each einsum.

  • _pmapping_row_filter_function (Optional[Callable[[Series], bool]]) – A function that takes in a row of the pmapping dataframe and returns True if the row should be included in the final mappings, and False otherwise. If None, all rows will be included.

Returns:

The mappings of the workload to the architecture.

Return type:

Mappings

mapper: FFM#

Configures the mapper used to map the workload onto the architecture.

mapping: Mapping#

How the workload is programmed onto the architecture. Do not specify this if you’d like the mapper to generate a mapping for you.

model: Model#

Configures the model used to evaluate mappings.

renames: Renames#

Aliases for tensors in the workload so that they can be called by canonical names when writing architecture constraints. For example, workload tensors may be renamed to “input”, “output”, and “weight”.

variables: Variables#

Variables that can be referenced in other places in the spec.

workload: Workload#

The program to be run on the arch.