Tensor Access Patterns (taplib)¶
taplib provides abstractions for describing how data is tiled and streamed
between memory and AIE compute tiles. A Tensor Access Pattern (TAP)
describes a multi-dimensional iteration over a buffer, generating the DMA
descriptor sequences that the NPU hardware executes.
TensorAccessPattern ¶
TensorAccessPattern(
tensor_dims: Sequence[int],
offset: int,
sizes: Sequence[int],
strides: Sequence[int],
)
A TensorAccessPattern represents a data access pattern applied to a tensor of a specific dimension. This is a base class meant to generically represent such as transformation using sizes, strides, and an offset.
An object representing an access pattern applied to a tensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor_dims
|
Sequence[int]
|
Dimensions of the tensor |
required |
offset
|
int
|
Offset into the tensor to begin the transformation |
required |
sizes
|
Sequence[int]
|
Transformation sizes |
required |
strides
|
Sequence[int]
|
Transformation strides |
required |
Source code in python/helpers/taplib/tap.py
tensor_dims
property
¶
A copy of the dimensions of the tensor
Returns:
| Type | Description |
|---|---|
Sequence[int]
|
Sequence[int]: Tensor dimensions |
offset
property
¶
Returns the offset into the tensor
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
offset |
sizes
property
¶
A copy of the access pattern sizes
Returns:
| Type | Description |
|---|---|
Sequence[int]
|
Sequence[int]: Transformation sizes |
strides
property
¶
A copy of the access pattern strides
Returns:
| Type | Description |
|---|---|
Sequence[int]
|
Sequence[int]: Trsnformation strides |
transformation_dims
property
¶
The access pattern represented as a sequence of (size, stride) tuples
Returns:
| Type | Description |
|---|---|
Sequence[tuple[int, int]]
|
Sequence[tuple[int, int]]: Transformation dimensions |
accesses ¶
Returns the access_order and access_count arrays.
The access_order ndarray sequentially counts access to elements in the tensor. If an element is accessed more than once, only the last count is reflected.
The access_count ndarray contains the number of times each element is accessed by the tensor access pattern.
Returns:
| Type | Description |
|---|---|
tuple[ndarray, ndarray]
|
tuple[np.ndarray, np.ndarray]: access_order, access_count |
Source code in python/helpers/taplib/tap.py
access_order ¶
The access_order ndarray sequentially counts access to elements in the tensor. If an element is accessed more than once, only the last count is reflected.
Returns:
| Type | Description |
|---|---|
ndarray
|
np.ndarray: access_order |
Source code in python/helpers/taplib/tap.py
access_count ¶
The access_count ndarray contains the number of times each element is accessed by the tensor access pattern.
Returns:
| Type | Description |
|---|---|
ndarray
|
np.ndarray: access_count |
Source code in python/helpers/taplib/tap.py
access_generator ¶
This function returns an iterator that returns the access index into the flattened tensor that this access pattern represents. This can be used to calculate the access count or to enumerate accesses.
Yields:
| Name | Type | Description |
|---|---|---|
int |
int
|
The next access index |
Source code in python/helpers/taplib/tap.py
compare_access_orders ¶
compare_access_orders(other: TensorAccessPattern) -> bool
This function creates an alternative way to compare access patterns. Sometimes access patterns with different sizes/strides are functionally equivalent; to detect functional equivalency, this function uses iterators produced by access_generator() to compare the access patterns. This is more performant than comparing the numpy array access_order or access_count tensors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
TensorAccessPattern
|
The TensorAccessPattern to compare to |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
other must be of type TensorAccessPattern |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if the TensorAccessPatterns are functionally equivalent; false otherwise. |
Source code in python/helpers/taplib/tap.py
visualize ¶
visualize(
show_arrows: bool | None = None,
title: str | None = None,
file_path: str | None = None,
show_plot: bool = True,
plot_access_count: bool = False,
) -> None
Visualize the TensorAccessPattern using a graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
show_arrows
|
bool | None
|
Display arrows between sequentially accessed elements. Defaults to None. |
None
|
title
|
str | None
|
Title of the produced graph. Defaults to None. |
None
|
file_path
|
str | None
|
Path to save the graph at; if none, it is not saved. Defaults to None. |
None
|
show_plot
|
bool
|
Show the plot (this is useful for Jupyter notebooks). Defaults to True. |
True
|
plot_access_count
|
bool
|
Plot the access count in addition to the access order. Defaults to False. |
False
|
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
This function is not implemented for all dimensions. |
Source code in python/helpers/taplib/tap.py
TensorAccessSequence ¶
TensorAccessSequence(
tensor_dims: Sequence[int],
num_steps: int,
offset: int | None = None,
sizes: Sequence[int] | None = None,
strides: Sequence[int] | None = None,
offset_fn: Callable[[int, int], int] | None = None,
sizes_fn: (
Callable[[int, Sequence[int]], Sequence[int]] | None
) = None,
strides_fn: (
Callable[[int, Sequence[int]], Sequence[int]] | None
) = None,
)
Bases: MutableSequence, Iterable
TensorAccessSequence is a MutableSequence and an Iterable. Generally, it is a thin wrapper around a list[TensorAccessPattern].
The TensorAccessSequence is useful as a container of TensorAccessPatterns so that a grouping of patterns may be accessed in a particular order, or visualized or animated in sequence.
A TensorAccessSequence is a sequence of TensorAccessPatterns modelled after a list.
The constructor can used given functions to generate a sequence of n steps. Allowed functions are the: * offset_fn(step: int, current_offset: int) -> new_offset: int * sizes_fn(step: int, current_sizes: Sequence[int]) -> new_sizes: Sequence[int] * strides_fn(step: int, currrent_strides: Sequence[int]) -> new_strides: Sequence[int]
In lieu or in addition to a function, a default value for sizes/strides/offsets may also be set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor_dims
|
Sequence[int]
|
Dimensions of the tensor. All TensorAccessPatterns in the sequence must share the tensor dimension. |
required |
num_steps
|
int
|
Number of steps (elements) in the sequence. |
required |
offset
|
int | None
|
Offset into the sequence. Defaults to None. |
None
|
sizes
|
Sequence[int] | None
|
Sizes for the TensorAccessPatterns Defaults to None. |
None
|
strides
|
Sequence[int] | None
|
Strides for the TensorAccessPatterns in the sequence. Defaults to None. |
None
|
offset_fn
|
Callable[[int, int], int] | None
|
A function to calculate the offset at each step. Defaults to None. |
None
|
sizes_fn
|
Callable[[int, Sequence[int]], Sequence[int]] | None
|
A function to calculate the sizes at each step. Defaults to None. |
None
|
strides_fn
|
Callable[[int, Sequence[int]], Sequence[int]] | None
|
A function to calculate the strides at teach step. Defaults to None. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
Parameters are validated |
Source code in python/helpers/taplib/tas.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | |
from_taps
classmethod
¶
from_taps(
taps: Sequence[TensorAccessPattern],
) -> TensorAccessSequence
This alternative constructor creates a TensorAccessSequence from a sequence of TensorAccessPatterns. This is an alternative to the traditional constructor, and is useful for patterns that are difficult to express using the sizes/strides/offset functions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
taps
|
Sequence[TensorAccessPattern]
|
The sequence of tensor access patterns |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
At least one TensorAccessPattern must be specified |
ValueError
|
All TensorAccessPatterns in a sequence must share tensor dimensions |
Returns:
| Name | Type | Description |
|---|---|---|
TensorAccessSequence |
TensorAccessSequence
|
A newly constructor TensorAccessSequence object |
Source code in python/helpers/taplib/tas.py
accesses ¶
Returns the access_order and access_count arrays of the TensorAccessPatterns in the sequence applied sequentially to the tensor.
The access_order ndarray sequentially counts access to elements in the tensor. If an element is accessed more than once, only the last count is reflected.
The access_count ndarray contains the number of times each element is accessed by the tensor access pattern.
Returns:
| Type | Description |
|---|---|
tuple[ndarray, ndarray]
|
tuple[np.ndarray, np.ndarray]: access_order, access_count |
Source code in python/helpers/taplib/tas.py
access_order ¶
The access_order ndarray sequentially counts access to elements in the tensor. If an element is accessed more than once, only the last count is reflected.
The TensorAccessPatterns in the sequence are applied sequentially.
Returns:
| Type | Description |
|---|---|
ndarray
|
np.ndarray: access_order |
Source code in python/helpers/taplib/tas.py
access_count ¶
The access_count ndarray contains the number of times each element is accessed by the tensor access pattern.
The TensorAccessPatterns in the sequence are applied sequentially.
Returns:
| Type | Description |
|---|---|
ndarray
|
np.ndarray: access_count |
Source code in python/helpers/taplib/tas.py
animate ¶
Creates and returns a handle to a TensorAccessSequence animation. Each frame in the animation represents one TensorAccessPattern in the sequence.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
title
|
str | None
|
The title of the animation. Defaults to None. |
None
|
animate_access_count
|
bool
|
Create an animation for the tensor access count, in addition to the tensor access order. Defaults to False. |
False
|
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
Not all dimensions of tensor may be visualized by animation at this time. |
Returns:
| Type | Description |
|---|---|
'FuncAnimation'
|
animation.FuncAnimation: A handle to the animation, produced by the matplotlib.animation module. |
Source code in python/helpers/taplib/tas.py
visualize ¶
visualize(
title: str | None = None,
file_path: str | None = None,
show_plot: bool = True,
plot_access_count: bool = False,
) -> None
Provides a visual of the TensorAccessSequence using a graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
title
|
str | None
|
The title of the graph. Defaults to None. |
None
|
file_path
|
str | None
|
The path to save the graph at. If None, it is not saved. Defaults to None. |
None
|
show_plot
|
bool
|
Show the plot; this is useful when running in a Jupyter notebook. Defaults to True. |
True
|
plot_access_count
|
bool
|
Plot the access count in addition to the access order. Defaults to False. |
False
|
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
Not all dimensions of tensor may be visualized. |
Source code in python/helpers/taplib/tas.py
compare_access_orders ¶
compare_access_orders(other: TensorAccessSequence) -> bool
This function creates an alternative way to compare access pattern sequences. Sometimes access patterns with different sizes/strides are functionally equivalent; to detect functional equivalency, this function uses iterators produced by access_generator() to compare the access patterns. This is more performant than comparing the numpy array access_order or access_count tensors, particularly when comparing sequences containing multiple tensor access patterns.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
TensorAccessSequence
|
The TensorAccessSequence to compare to |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True is functionally equivalent; False otherwise. |
Source code in python/helpers/taplib/tas.py
TensorTiler2D ¶
This is a generator (similar to factory pattern) class which produces TensorAccessSequences for common 2-dimensional tiling patterns.
Source code in python/helpers/taplib/tensortiler2d.py
simple_tiler
classmethod
¶
simple_tiler(
tensor_dims: Sequence[int],
tile_dims: Sequence[int] | None = None,
tile_col_major: bool = False,
iter_col_major: bool = False,
pattern_repeat: int = 1,
prune_step: bool = True,
) -> TensorAccessSequence
The simple_tiler is a special case of the group_tiler. The simple_tiler produces a TensorAccessSequence with one TensorAccessPattern per tile.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor_dims
|
Sequence[int]
|
The dimensions of the tensor to tile. |
required |
tile_dims
|
Sequence[int] | None
|
The dimension of the tile. If None, the tile_dims is set equal to the tensor_dims. Defaults to None. |
None
|
tile_col_major
|
bool
|
Iterate column major within each tile. Defaults to False. |
False
|
iter_col_major
|
bool
|
Iterate column major over tiles within the TensorAccessSequence. Defaults to False. |
False
|
pattern_repeat
|
int
|
Access a tile n times per TensorAccessPattern. Defaults to 1. |
1
|
prune_step
|
bool
|
Prune the iteration steps in the tiling process. Defaults to True. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
TensorAccessSequence |
TensorAccessSequence
|
A TensorAccessSequence with one TensorAccessPattern per tile |
Source code in python/helpers/taplib/tensortiler2d.py
group_tiler
classmethod
¶
group_tiler(
tensor_dims: Sequence[int],
tile_dims: Sequence[int],
tile_group_dims: Sequence[int] | None = None,
tile_col_major: bool = False,
tile_group_col_major: bool = False,
iter_col_major: bool = False,
pattern_repeat: int = 1,
allow_partial: bool = False,
prune_step: bool = True,
) -> TensorAccessSequence
The group_tiler is a special case of the step_tiler. The group_tiler produces a TensorAccessSequence with a group of tiles per TensorAccesspattern in the sequence.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor_dims
|
Sequence[int]
|
The dimensions of the tensor to tile. |
required |
tile_dims
|
Sequence[int]
|
The dimension of the tile (a contiguous group of elements) |
required |
tile_group_dims
|
Sequence[int] | None
|
Dimensions of the grouping of tiles, specified by number of tiles (not elements). If None, assumed to be (1, 1). Defaults to None. |
None
|
tile_col_major
|
bool
|
Iterate column major within each tile. Defaults to False. |
False
|
tile_group_col_major
|
bool
|
Iterate column major between tiles in a group within a TensorAccessSequence. Defaults to False. |
False
|
iter_col_major
|
bool
|
Iterate column major over tiles within the TensorAccessSequence. Defaults to False. |
False
|
pattern_repeat
|
int
|
Apply a pattern n times within a single TensorAccessPattern. Defaults to 1. |
1
|
allow_partial
|
bool
|
While a tensor must decompose into tiles easily, a tensor may not decompose into tile groups evenly. If True, uneven groups are allowed. If false, an exception will be thrown. Defaults to False. |
False
|
prune_step
|
bool
|
Prune the iteration steps in the tiling process. Defaults to True. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
TensorAccessSequence |
TensorAccessSequence
|
A TensorAccessSequence with one tile grouping per TensorAccessPattern |
Source code in python/helpers/taplib/tensortiler2d.py
step_tiler
classmethod
¶
step_tiler(
tensor_dims: Sequence[int],
tile_dims: Sequence[int],
tile_group_repeats: Sequence[int],
tile_group_steps: Sequence[int] | None = None,
tile_col_major: bool = False,
tile_group_col_major: bool = False,
iter_col_major: bool = False,
allow_partial: bool = False,
pattern_repeat: int = 1,
prune_step: bool = True,
) -> TensorAccessSequence
Build a TensorAccessSequence by tiling a tensor with explicit per-dimension steps.
This is the general-purpose tiler that the simpler simple_tiler /
group_tiler factories delegate to. It produces one
TensorAccessPattern per tile group, giving full control over tile
size, group repeats, per-dimension step, and iteration order.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor_dims
|
Sequence[int]
|
The dimensions of the tensor to tile. |
required |
tile_dims
|
Sequence[int]
|
The dimension of the tile (a contiguous group of elements) |
required |
tile_group_repeats
|
Sequence[int]
|
Number of times a tile appears in each dimension in each TensorAccessPattern. |
required |
tile_group_steps
|
Sequence[int] | None
|
Space between each tile repeat in each dimension, given in units of tile size. Defaults to None. |
None
|
tile_col_major
|
bool
|
Iterate column major within each tile. Defaults to False. |
False
|
tile_group_col_major
|
bool
|
Iterate column major between tiles in a group within a TensorAccessSequence. Defaults to False. |
False
|
iter_col_major
|
bool
|
Iterate column major over tiles within the TensorAccessSequence. Defaults to False. |
False
|
allow_partial
|
bool
|
Whether to allow partial tile groups. A tensor always decomposes into tiles evenly, but it may not decompose into tile groups evenly. When False, a partial tile grouping raises a ValueError; when True, partial groupings at the tensor edges are permitted. Defaults to False. |
False
|
pattern_repeat
|
int
|
Apply the access pattern n times within a single TensorAccessPattern. Defaults to 1. |
1
|
prune_step
|
bool
|
Prune the iteration steps in the tiling process. Defaults to True. |
True
|
Raises:
| Type | Description |
|---|---|
ValueError
|
The parameters are validated |
ValueError
|
Some transformations are not expressible in only 4 dimensions of sizes/strides |
ValueError
|
If allow_partial is False, an error will be thrown if partial TensorAccessPatterns are needed to fully tile the tensor. |
Returns:
| Name | Type | Description |
|---|---|---|
TensorAccessSequence |
TensorAccessSequence
|
A TensorAccessSequence with one tile grouping per TensorAccessPattern, where the tile grouping may or may not be contiguous. |
Source code in python/helpers/taplib/tensortiler2d.py
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | |
Utilities¶
validate_and_clean_sizes_strides ¶
validate_and_clean_sizes_strides(
sizes: Sequence[int] | None,
strides: Sequence[int] | None,
allow_none: bool = False,
expected_dims: int | None = None,
) -> tuple[Sequence[int] | None, Sequence[int] | None]
This is a helper function to validate sizes, strides and remove any unused values from upper dimensions if possible.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sizes
|
Sequence[int] | None
|
The transformation strides, or None |
required |
strides
|
Sequence[int] | None
|
The transformation sizes, or None |
required |
allow_none
|
bool
|
Allow sizes and/or strides to be None. Defaults to False. |
False
|
expected_dims
|
int | None
|
Number of dimensions expected for both sizes and strides. Defaults to None. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
Validate sizes and strides |
Returns:
| Type | Description |
|---|---|
tuple[Sequence[int] | None, Sequence[int] | None]
|
tuple[Sequence[int] | None, Sequence[int] | None]: The 'cleaned' sizes and strides. |
Source code in python/helpers/taplib/utils.py
validate_tensor_dims ¶
validate_tensor_dims(
tensor_dims: Sequence[int],
expected_dims: int | None = None,
) -> Sequence[int]
This is a helper function used to validate dimensions of tensors, namely be ensuring each dimension is > 0 and the dimensionality is as expected.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor_dims
|
Sequence[int]
|
Tensor dimensions to check |
required |
expected_dims
|
int | None
|
Expected number of dimensions. Defaults to None. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
Validate the tensor dimensions |
Returns:
| Type | Description |
|---|---|
Sequence[int]
|
Sequence[int]: The validated tensor dimensions. |
Source code in python/helpers/taplib/utils.py
validate_offset ¶
This is a helper function to validate an offset into the tensor. It primarily checks to see if the offset is a valid index to the tensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
offset
|
int
|
The offset to check. |
required |
tensor_dims
|
Sequence[int] | None
|
The dimensions of the tensor the offset corresponds to. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
Validate the offset. |
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The validated offset. |