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
¶
Return 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]: Transformation 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 ¶
Return 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 ¶
Return the access_order ndarray, which 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 ¶
Return the access_count ndarray, which contains the number of times each element is accessed.
Returns:
| Type | Description |
|---|---|
ndarray
|
np.ndarray: access_count |
Source code in python/helpers/taplib/tap.py
access_generator ¶
Return an iterator over the access indices 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
Compare access patterns for functional equivalency.
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
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 127 128 129 130 131 132 133 134 135 136 137 138 139 | |
from_taps
classmethod
¶
from_taps(
taps: Sequence[TensorAccessPattern],
) -> TensorAccessSequence
Create 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 ¶
Return the access_order and access_count arrays of 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 ¶
Return the access_order ndarray, which 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 ¶
Return the access_count ndarray, which contains the number of times each element is accessed.
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 ¶
Create and return 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
Provide 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
Compare access pattern sequences for functional equivalency.
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 ¶
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
Produce a TensorAccessSequence with one TensorAccessPattern per tile.
The simple_tiler is a special case of the group_tiler.
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
Produce a TensorAccessSequence with a group of tiles per TensorAccessPattern in the sequence.
The group_tiler is a special case of the step_tiler.
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
111 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 271 272 | |
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]
Validate sizes and 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]
Validate dimensions of tensors by 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 ¶
Validate an offset into the tensor.
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. |