MatmulTileScenario
Optimization scenarios · Implementation: mlsysim/engine/scenario_definitions/optimization.py.
Construct this scenario with keyword inputs. The fields below show the types and defaults declared by this class.
C = A B with A m x k and B k x n, computed one tile_m x tile_n output tile at a time, stepping through the reduction tile_k elements per step.
Operands are operand_bytes each and the accumulator accumulator_bytes. The on-chip store holds one A tile and one B tile (two of each when double buffered) and the accumulator tile. Traffic counts element moves between memory and the on-chip store: A is loaded once per output-tile column, B once per output-tile row, and C written once. The single-cell loop orders (no tile) count one held value per cell: the other operands stream once per MAC, and a partial sum that is not held is read and written once per MAC.
Notes
Equation: The calculation members below define macs, flops, tiles_m, tiles_n, tiles_k, output_tiles, tile_products, tile_product_flops, tile_product_bytes, tile_intensity, unblocked_intensity, compulsory_intensity, buffer_copies, a_tile_bytes, b_tile_bytes, accumulator_tile_bytes, operand_tile_bytes, live_bytes, fits, a_bytes, a_elements, b_elements, c_elements, a_moves, b_moves, tiled_moves, global_loads_per_mac, partial_sum_moves, a_stationary_moves, output_stationary_moves, b_stationary_moves, row_b_reads.
Assumptions: Dense multiplication uses two FLOPs per MAC and fixed-width operands/accumulators; full-tile work counts padded edges.
Excludes: Bank conflicts, cache effects, scheduling overhead, and precision-dependent arithmetic throughput.
References
Derivation: C = A B with A m x k and B k x n, computed one tile_m x tile_n output tile at a time, stepping through the reduction tile_k elements per step. Each member records the corresponding algebra or named physics function.
Examples
Evaluate the named configuration and display a modeled result.
>>> from mlsysim import Scenarios
>>> case = Scenarios.Matmul4096Fp16Tile128
>>> value = case.tile_intensity
>>> print(f"{value:.3g}")
64Attributes
| Name | Description |
|---|---|
| a_bytes | Full A-matrix storage in bytes at operand precision. |
| a_elements | Number of elements in the M-by-K input matrix A. |
| a_moves | A-element reads when A is reloaded for every output tile column. |
| a_stationary_moves | Element transfers when each cell retains A while B and partial sums stream. |
| a_tile_bytes | Live A-tile operand buffers in bytes, including double buffering if enabled. |
| accumulator_bytes | |
| accumulator_tile_bytes | Output-tile accumulator storage in bytes at accumulator precision. |
| b_elements | Number of elements in the K-by-N input matrix B. |
| b_moves | B-element reads when B is reloaded for every output tile row. |
| b_stationary_moves | Element transfers when each cell retains B while A and partial sums stream. |
| b_tile_bytes | Live B-tile operand buffers in bytes, including double buffering if enabled. |
| buffer_copies | Operand buffer-copy count: two for double buffering, otherwise one. |
| c_elements | Number of elements in the M-by-N output matrix C. |
| compulsory_intensity | FLOP/byte if each A, B, and C element moves exactly once at operand precision. |
| double_buffered | |
| flops | Dense multiplication work in FLOPs, two operations per MAC. |
| global_loads_per_mac | Operand loads per MAC for a full tile, reciprocal tile dimensions summed. |
| k | |
| live_bytes | Combined operand and accumulator bytes simultaneously resident. |
| m | |
| macs | Multiply-accumulate count for dense M-by-K times K-by-N multiplication. |
| n | |
| operand_bytes | |
| operand_tile_bytes | Combined A and B operand-buffer bytes, excluding accumulators. |
| output_stationary_moves | Element transfers when output sums remain local and both operands stream. |
| output_tiles | Number of output tiles, tile rows times tile columns. |
| partial_sum_moves | Partial-sum transfers if each MAC reads and writes its sum. |
| tile_intensity | FLOP per operand byte loaded for a full tile, excluding output traffic. |
| tile_k | |
| tile_m | |
| tile_n | |
| tile_product_bytes | Operand bytes loaded for one full A-tile/B-tile product. |
| tile_product_flops | FLOPs for one full tile product; edge padding is counted as full work. |
| tile_products | Tile products required, one per output tile and reduction slice. |
| tiled_moves | Total element transfers: tiled A and B reads plus one output write. |
| tiles_k | Reduction tile count, rounding K up to a multiple of reduction width. |
| tiles_m | Output tile-row count, rounding M up to a multiple of tile height. |
| tiles_n | Output tile-column count, rounding N up to a multiple of tile width. |
| unblocked_intensity | FLOP/byte when every MAC loads both operands without reuse. |
Methods
| Name | Description |
|---|---|
| fits | Whether live bytes fit the supplied capacity quantity; equality is feasible. |
| row_b_reads | B-element reads after reuse along cells cells; integer division requires complete sharing groups. |
fits
engine.scenario_types.MatmulTileScenario.fits(capacity)Whether live bytes fit the supplied capacity quantity; equality is feasible.
Equation: bool(live_bytes <= capacity).
row_b_reads
engine.scenario_types.MatmulTileScenario.row_b_reads(cells)B-element reads after reuse along cells cells; integer division requires complete sharing groups.
B reads when each B value passes along a row of cells cells holding A values.
Equation: macs // cells.
m
Type: int.
Declared default: required.
n
Type: int.
Declared default: required.
k
Type: int.
Declared default: required.
tile_m
Type: int.
Declared default: required.
tile_n
Type: int.
Declared default: required.
tile_k
Type: int.
Declared default: required.
operand_bytes
Type: Quantity.
Declared default: required.
accumulator_bytes
Type: Quantity.
Declared default: required.
double_buffered
Type: bool.
Declared default: False.
macs
engine.scenario_types.MatmulTileScenario.macs
Multiply-accumulate count for dense M-by-K times K-by-N multiplication.
Equation: m * n * k.
flops
engine.scenario_types.MatmulTileScenario.flops
Dense multiplication work in FLOPs, two operations per MAC.
Equation: Q_(2 * macs, 'flop').
tiles_m
engine.scenario_types.MatmulTileScenario.tiles_m
Output tile-row count, rounding M up to a multiple of tile height.
Equation: -(-m // tile_m).
tiles_n
engine.scenario_types.MatmulTileScenario.tiles_n
Output tile-column count, rounding N up to a multiple of tile width.
Equation: -(-n // tile_n).
tiles_k
engine.scenario_types.MatmulTileScenario.tiles_k
Reduction tile count, rounding K up to a multiple of reduction width.
Equation: -(-k // tile_k).
output_tiles
engine.scenario_types.MatmulTileScenario.output_tiles
Number of output tiles, tile rows times tile columns.
Equation: tiles_m * tiles_n.
tile_products
engine.scenario_types.MatmulTileScenario.tile_products
Tile products required, one per output tile and reduction slice.
A-tile-by-B-tile products: every output tile sums tiles_k of them.
Equation: output_tiles * tiles_k.
tile_product_flops
engine.scenario_types.MatmulTileScenario.tile_product_flops
FLOPs for one full tile product; edge padding is counted as full work.
Equation: Q_(2 * tile_m * tile_n * tile_k, 'flop').
tile_product_bytes
engine.scenario_types.MatmulTileScenario.tile_product_bytes
Operand bytes loaded for one full A-tile/B-tile product.
One A tile and one B tile loaded.
Equation: ((tile_m * tile_k + tile_k * tile_n) * operand_bytes).to('byte').
tile_intensity
engine.scenario_types.MatmulTileScenario.tile_intensity
FLOP per operand byte loaded for a full tile, excluding output traffic.
FLOP per operand byte loaded: (2 / b) T_M T_N / (T_M + T_N), independent of T_K.
Equation: (tile_product_flops / tile_product_bytes).to('flop/byte').magnitude.
unblocked_intensity
engine.scenario_types.MatmulTileScenario.unblocked_intensity
FLOP/byte when every MAC loads both operands without reuse.
No reuse: every MAC (2 FLOP) loads its two operands.
Equation: (Q_(2, 'flop') / (2 * operand_bytes)).to('flop/byte').magnitude.
compulsory_intensity
engine.scenario_types.MatmulTileScenario.compulsory_intensity
FLOP/byte if each A, B, and C element moves exactly once at operand precision.
Each of A, B, and C moved exactly once, all at operand_bytes.
Equation: (flops / moved).to('flop/byte').magnitude.
buffer_copies
engine.scenario_types.MatmulTileScenario.buffer_copies
Operand buffer-copy count: two for double buffering, otherwise one.
Equation: 2 if double_buffered else 1.
a_tile_bytes
engine.scenario_types.MatmulTileScenario.a_tile_bytes
Live A-tile operand buffers in bytes, including double buffering if enabled.
Equation: (buffer_copies * tile_m * tile_k * operand_bytes).to('byte').
b_tile_bytes
engine.scenario_types.MatmulTileScenario.b_tile_bytes
Live B-tile operand buffers in bytes, including double buffering if enabled.
Equation: (buffer_copies * tile_k * tile_n * operand_bytes).to('byte').
accumulator_tile_bytes
engine.scenario_types.MatmulTileScenario.accumulator_tile_bytes
Output-tile accumulator storage in bytes at accumulator precision.
Equation: (tile_m * tile_n * accumulator_bytes).to('byte').
operand_tile_bytes
engine.scenario_types.MatmulTileScenario.operand_tile_bytes
Combined A and B operand-buffer bytes, excluding accumulators.
The A and B buffers alone (what a GPU stages in shared memory).
Equation: a_tile_bytes + b_tile_bytes.
live_bytes
engine.scenario_types.MatmulTileScenario.live_bytes
Combined operand and accumulator bytes simultaneously resident.
Every buffer live at once: 2 T_M T_K + 2 T_K T_N + 4 T_M T_N bytes for FP16 operands, FP32 sums.
Equation: operand_tile_bytes + accumulator_tile_bytes.
a_bytes
engine.scenario_types.MatmulTileScenario.a_bytes
Full A-matrix storage in bytes at operand precision.
Equation: (m * k * operand_bytes).to('byte').
a_elements
engine.scenario_types.MatmulTileScenario.a_elements
Number of elements in the M-by-K input matrix A.
Equation: m * k.
b_elements
engine.scenario_types.MatmulTileScenario.b_elements
Number of elements in the K-by-N input matrix B.
Equation: k * n.
c_elements
engine.scenario_types.MatmulTileScenario.c_elements
Number of elements in the M-by-N output matrix C.
Equation: m * n.
a_moves
engine.scenario_types.MatmulTileScenario.a_moves
A-element reads when A is reloaded for every output tile column.
Equation: a_elements * tiles_n.
b_moves
engine.scenario_types.MatmulTileScenario.b_moves
B-element reads when B is reloaded for every output tile row.
Equation: b_elements * tiles_m.
tiled_moves
engine.scenario_types.MatmulTileScenario.tiled_moves
Total element transfers: tiled A and B reads plus one output write.
Element moves with the tiling: A per output-tile column, B per output-tile row, C once.
Equation: a_moves + b_moves + c_elements.
global_loads_per_mac
engine.scenario_types.MatmulTileScenario.global_loads_per_mac
Operand loads per MAC for a full tile, reciprocal tile dimensions summed.
Operand loads from memory per MAC inside a full tile: 1/T_N + 1/T_M.
Equation: 1 / tile_n + 1 / tile_m.
partial_sum_moves
engine.scenario_types.MatmulTileScenario.partial_sum_moves
Partial-sum transfers if each MAC reads and writes its sum.
A partial sum read and written once per MAC.
Equation: 2 * macs.
a_stationary_moves
engine.scenario_types.MatmulTileScenario.a_stationary_moves
Element transfers when each cell retains A while B and partial sums stream.
One cell holds an A value: A loaded once; B and the partial sums stream.
Equation: a_elements + macs + partial_sum_moves.
output_stationary_moves
engine.scenario_types.MatmulTileScenario.output_stationary_moves
Element transfers when output sums remain local and both operands stream.
One cell holds the running sum: A and B stream, C written once.
Equation: 2 * macs + c_elements.
b_stationary_moves
engine.scenario_types.MatmulTileScenario.b_stationary_moves
Element transfers when each cell retains B while A and partial sums stream.
One cell holds a B value: B loaded once; A and the partial sums stream.
Equation: b_elements + macs + partial_sum_moves.