Archx
An event-based cost-modeling framework for computer-system design-space exploration, built around the A-Graph abstraction.
Overview
Archx computes arbitrary hardware metrics for an architecture running a workload. It does this by:
- building a directed graph (the A-Graph) of events and hardware modules connected by subevent edges,
- populating each hardware module with costs queried from a pluggable hardware interface (the CACTI7 memory model, CMOS synthesis CSVs, ...),
- running user-supplied Python performance models that set per-edge call counts, and
- aggregating metrics up the graph to answer queries such as "total energy of a GEMM on this accelerator".
The graph engine is implemented in Rust and exposed to Python as archx._core; everything else is Python.
Archx models across the system stack, separating into four levels. Each level is described by one of the four inputs to a run, detailed under Configuration.
| level | what it describes | input |
|---|---|---|
| Application | a workload (LLM, signal processing, error correction, ...), defined with parameters to sweep through multiple configurations | workload (-w) |
| Software | an event graph decomposing the application into architecture events, each with an isolated Python performance model that translates the workload configuration into per-subevent call counts | event (-e) |
| Architecture | the micro-architecture blocks that build the overall architecture, at any granularity | architecture (-a) |
| Circuit | the physical costs of each module: area, power, energy, cycle count, runtime, or any user-defined quantity, supplied per module by a hardware interface | metric (-m) |
For the package layout, the seven pipeline stages, and how caching works, see ARCHITECTURE.md.
Requirements
- Anaconda to manage the environment.
- The Rust toolchain for a source installation only, to compile the Rust extension via Maturin. Installing from PyPI needs no Rust.
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env" # add cargo/rustc to PATH in the current shell
rustc --version # verify
Installation
Both methods provide the archx CLI command and the import archx Python module.
Option 1: conda + pip install from PyPI (recommended)
Installs all dependencies via conda and the Archx package from PyPI.
conda env create -f environment.yaml # edit `name: archx` to rename
conda activate archx
pip install archx
Option 2: source installation (developer mode)
Editable install from source: live code changes are reflected without reinstalling.
git clone https://github.com/UnaryLab/archx.git && cd archx
conda env create -f environment.yaml # edit `name: archx` to rename
conda activate archx
pip install -e . --no-deps # editable install; Rust extension is compiled here
After editing any Rust source under src/archx/rust-core/, rerun pip install -e . --no-deps to recompile; Python changes are live without reinstalling.
Validate
archx -h
python -c "import archx"
Quick start
Run one design and query a metric from the result.
archx -r <run_dir> \
-a arch.yaml -m metric.yaml -w workload.yaml -e event.yaml \
-c <run_dir>/graph.json \
[-t] [-s] [-d] [-l DEBUG] [-p <dir>]
-cis the checkpoint the populated A-Graph is saved to (must end in.json).-tmirrors the log to the terminal (a logfile is always written into the run dir).-salso dumps the parsed architecture/metric/workload/event dicts as YAML into the run dir.-ddeletes the run dir first if it exists.-padds a directory tosys.pathso performance models can import local helpers.
Load the checkpoint and aggregate any metric at any event:
from archx.event import load_event_graph
from archx.metric import create_metric_dict, aggregate_event_metric
event_graph = load_event_graph('<run_dir>/graph.json')
metric_dict = create_metric_dict('metric.yaml')
result = aggregate_event_metric(event_graph=event_graph, metric_dict=metric_dict,
metric='dynamic_energy', workload='gemm', event='gemm')
# -> OrderedDict({'value': ..., 'unit': 'nJ'})
aggregate_tag_metric aggregates over all modules sharing an architecture tag, and query_module_metric reads a single module's raw metrics.
For runnable designs with all four inputs written out, see examples/README.md.
Reproducing results
Design-space sweeps
A Python description file defining a description(path) function, built on archx.programming which uses OR-Tools CP-SAT to enumerate valid configurations under constraints, drives batch exploration:
archx -r <run_dir> -compile description.py # generate configurations.csv
archx -r <run_dir> -extract configurations.csv # csv -> runs.txt
archx -r <run_dir> -f configurations.csv # Tkinter GUI to filter -> runs.txt
archx -r <run_dir> -x runs.txt # execute all runs in parallel
-compile ... -full chains all of the above in one command (add -ff to insert the GUI filter step). -x fans the runs out across all CPU cores; failing runs are collected in failed_runs.txt.
Writing a description file
A description file builds the same four inputs as a single run, but programmatically, and declares which parameters to sweep. Any list-valued instance or query entry, and any workload parameter added with sweep=True, becomes a sweep axis; constraints prune invalid combinations before anything is written to disk.
from archx.programming.graph.agraph import AGraph
def description(path):
agraph = AGraph(path=path)
architecture = agraph.architecture
event = agraph.event
metric = agraph.metric
workload = agraph.workload
# Architecture: list values become sweep axes.
architecture.add_attributes(technology=[45], frequency=400, interface='csv_cmos')
pe = architecture.add_module(name='pe', instance=[[16, 16], [32, 32], [64, 64]], tag=['onchip', 'compute'], query={'class': 'mac'})
sram = architecture.add_module(name='sram', instance=[1], tag=['memory'], query={'interface': 'cacti7', 'class': 'sram', 'bank': [32, 64, 128], 'width': 16, 'depth': [512, 1024, 2048]})
# Events: the A-Graph structure, same as the event YAML.
event.add_event(name='gemm', subevent=['mac_array', 'sram_rd', 'sram_wr'], performance='performance.py')
event.add_event(name='mac_array', subevent=['pe'], performance='performance.py')
event.add_event(name='sram_rd', subevent=['sram'], performance='performance.py')
event.add_event(name='sram_wr', subevent=['sram'], performance='performance.py')
# Metrics.
metric.add_metric(name='area', unit='mm^2', aggregation='module')
metric.add_metric(name='dynamic_energy', unit='nJ', aggregation='summation')
metric.add_metric(name='runtime', unit='ms', aggregation='specified')
# Workloads: sweep=True parameters become sweep axes.
gemm = workload.add_configuration(name='gemm')
gemm.add_parameter(parameter_name='m', parameter_value=[256, 512, 1024], sweep=True)
gemm.add_parameter(parameter_name='k', parameter_value=512)
gemm.add_parameter(parameter_name='n', parameter_value=512)
# Constraints prune the cross product of all axes.
# direct_constraint: the listed parameters sweep together by index
# (the i-th PE shape only pairs with the i-th bank count).
agraph.direct_constraint([pe['instance'], sram['query']['bank']])
# conditional_constraint: keep only combinations whose actual values
# satisfy an arbitrary condition (here: SRAM capacity capped at 4 Mib).
agraph.conditional_constraint(a=sram['query']['bank'], b=sram['query']['depth'], condition=lambda bank, depth: bank * depth * 16 <= 2**22)
agraph.generate()
return agraph
The handles returned by add_module index into the swept parameters (pe['instance'], sram['query']['bank']); passing a list of names (e.g. name=['isram', 'wsram']) creates several identically-parameterized modules, indexed as srams['wsram']['query']['bank']. agraph.generate() solves the constraint model and writes the per-configuration YAML files (architecture/, workload/, event/, metric/) plus configurations.csv into the run directory; -extract then turns the CSV into one archx command line per configuration in runs.txt.
For a complete real-world description (multi-module arrays, partition and multi-variable conditional constraints), see zoo/chiplet4ai/llama/description.py.
Batch runs
bash src/archx/bin/run_archx.sh runs.txt
Tests
pytest
tests/test_numerical_equivalence.py pins the Rust aggregation engine against hand-derived values. Tests touching SRAM run CACTI7, which ships a binary per host as cacti-<system>-<machine> and is built from source when the matching one is absent.
Configuration
A run is described by four YAML files plus one or more Python performance models.
Architecture (-a)
The hardware: a flattened set of named modules. attribute holds global defaults (technology, frequency, default interface) that are merged into each module's query; the query dict is what gets sent to the hardware interface to price the module. Modules can path: to other architecture YAML files for hierarchical descriptions, carry tag: lists for group queries, and instance: lists for arrays of identical units.
architecture:
attribute:
technology: 45 # nm
frequency: 400 # MHz
interface: csv_cmos # default hardware interface
module:
mac_array:
path: mac_array.architecture.yaml # include another file
sram:
tag: [memory, onchip]
query:
interface: cacti7
class: sram
bank: 32
width: 64 # bits
depth: 1024
Metric (-m)
The metrics to compute. Each metric declares a unit and an aggregation mode:
| mode | meaning | typical metrics |
|---|---|---|
module |
sum once over distinct modules | area, leakage power |
summation |
sum scaled by per-edge call counts (default) | dynamic energy |
specified |
taken directly from a performance-model output | cycle count, runtime |
metric:
area:
unit: mm^2
aggregation: module
dynamic_energy:
unit: nJ # aggregation defaults to summation
runtime:
unit: ms
aggregation: specified
Workload (-w)
One workload per file: a name and a configuration dict of knobs the performance models read. A file may instead path: to another workload file, which is followed recursively.
workload:
name: llama_3_70b
configuration:
batch_size: 32
dim: 8192
layers: 80
Event (-e)
The A-Graph structure: each event lists its subevents (other events, or leaf hardware modules from the architecture) and the Python file holding its performance model.
event:
gemm:
subevent: [mac_array, sram_rd, sram_wr]
performance: performance/example.performance.py
sram_rd:
subevent: [sram]
performance: performance/example.performance.py
Performance models
For each event, a Python function with the same name as the event:
def gemm(architecture_dict, workload_dict=None):
cfg = workload_dict['configuration']
macs = cfg['m'] * cfg['k'] * cfg['n']
return OrderedDict({
'subevent': OrderedDict({
'mac_array': OrderedDict({'count': macs / array_size}),
'sram_rd': OrderedDict({'count': reads}),
}),
})
It receives the parsed architecture and workload dicts and returns, per subevent, the call count (and optionally an operation such as read/write for multi-operation modules like SRAM). It may also return specified metrics directly (e.g. {'cycle_count': {'value': 1., 'unit': 'cycles'}}). See examples/mac_1_cycle/input/performance/example.performance.py for a complete model.
Hardware interfaces
Interfaces are the pluggable cost models that price each module, under src/archx/interface/:
| interface | costs |
|---|---|
cacti7 |
SRAM/DRAM area, power, and energy via the CACTI7 memory model (bundled C++ source, one binary per host) |
csv_cmos |
logic modules at 45 nm and 7 nm, interpolated from CMOS synthesis and place-and-route CSVs |
csv_cmos_32nm |
the same lookup over a 32 nm library |
csv_cmos_asplos_2026_ae |
the same lookup over a second 45 nm library |
chiplet_cmos |
CMOS CSV costs for chiplet-based designs |
csv_sc |
stochastic-computing modules |
csv_h200 |
measured H200 power and runtime per GPU kernel |
csv_riscv |
per-stage RISC-V energy |
A module selects one with the interface: key in its query, or inherits the architecture's global attribute. Register, unregister, or copy an interface with:
archx -ireg -iname <name> -idir <dir> # register a new hardware interface
archx -iureg -iname <name> # unregister
archx -icopy -iname <name> -idir <dir> # copy an installed interface out
See src/archx/interface/README.md for the query contract and how to add your own.
Citation
Not yet published.
License
MIT. See LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file archx-0.1.1.tar.gz.
File metadata
- Download URL: archx-0.1.1.tar.gz
- Upload date:
- Size: 1.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
289149e7f3d1734cd657bddf1bca2bc6e92209a85f1ae31655cb15796cf9113e
|
|
| MD5 |
1f38f3cc50b9fe0a3a776e8e39cf0670
|
|
| BLAKE2b-256 |
08da5cc9342ef80ace4e9341352af44b87cf8fb815bc5a9eec491b9d28034550
|
Provenance
The following attestation bundles were made for archx-0.1.1.tar.gz:
Publisher:
publish.yaml on UnaryLab/archx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
archx-0.1.1.tar.gz -
Subject digest:
289149e7f3d1734cd657bddf1bca2bc6e92209a85f1ae31655cb15796cf9113e - Sigstore transparency entry: 2254449256
- Sigstore integration time:
-
Permalink:
UnaryLab/archx@7e514754d05999490975d74c7248f3d6b4e34bc3 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/UnaryLab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@7e514754d05999490975d74c7248f3d6b4e34bc3 -
Trigger Event:
release
-
Statement type:
File details
Details for the file archx-0.1.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: archx-0.1.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 3.4 MB
- Tags: CPython 3.10+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3efff1b85917bc66e72e8370473ca295c70d7e7fa1f584b0d266471a934ffc5c
|
|
| MD5 |
887e9fe8100366a12f55bb009c7b2a9c
|
|
| BLAKE2b-256 |
aef647f1cfee69575142162446b1b4e27cdd9ac22eea611b3ba2c0dd0d9ceeee
|
Provenance
The following attestation bundles were made for archx-0.1.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
publish.yaml on UnaryLab/archx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
archx-0.1.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
3efff1b85917bc66e72e8370473ca295c70d7e7fa1f584b0d266471a934ffc5c - Sigstore transparency entry: 2254449293
- Sigstore integration time:
-
Permalink:
UnaryLab/archx@7e514754d05999490975d74c7248f3d6b4e34bc3 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/UnaryLab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@7e514754d05999490975d74c7248f3d6b4e34bc3 -
Trigger Event:
release
-
Statement type:
File details
Details for the file archx-0.1.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: archx-0.1.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 3.4 MB
- Tags: CPython 3.10+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c266093829b260f1062a193b266c2c0d1f35ac3525ae43abc8cdad61ab72fe2b
|
|
| MD5 |
517b7b63b488012e16d09f06e4d10b7a
|
|
| BLAKE2b-256 |
0c1285a9d61278f366257876f25b0f3f9257cb602db4ee214e85f2c97b3c295e
|
Provenance
The following attestation bundles were made for archx-0.1.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
publish.yaml on UnaryLab/archx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
archx-0.1.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
c266093829b260f1062a193b266c2c0d1f35ac3525ae43abc8cdad61ab72fe2b - Sigstore transparency entry: 2254449316
- Sigstore integration time:
-
Permalink:
UnaryLab/archx@7e514754d05999490975d74c7248f3d6b4e34bc3 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/UnaryLab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@7e514754d05999490975d74c7248f3d6b4e34bc3 -
Trigger Event:
release
-
Statement type:
File details
Details for the file archx-0.1.1-cp310-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: archx-0.1.1-cp310-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.3 MB
- Tags: CPython 3.10+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9596619f8c185e56dbc0dcab306f992f86d3ee1a09be1cf38ce3c61d1768eba4
|
|
| MD5 |
5b8c6cca9ece1b1e6a0fea6e7b711a87
|
|
| BLAKE2b-256 |
17ea39cc224e2eb9658e1d1d424695d5439016ddb59c53587221f1cbce80df21
|
Provenance
The following attestation bundles were made for archx-0.1.1-cp310-abi3-macosx_11_0_arm64.whl:
Publisher:
publish.yaml on UnaryLab/archx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
archx-0.1.1-cp310-abi3-macosx_11_0_arm64.whl -
Subject digest:
9596619f8c185e56dbc0dcab306f992f86d3ee1a09be1cf38ce3c61d1768eba4 - Sigstore transparency entry: 2254449340
- Sigstore integration time:
-
Permalink:
UnaryLab/archx@7e514754d05999490975d74c7248f3d6b4e34bc3 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/UnaryLab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@7e514754d05999490975d74c7248f3d6b4e34bc3 -
Trigger Event:
release
-
Statement type:
File details
Details for the file archx-0.1.1-cp310-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: archx-0.1.1-cp310-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 3.3 MB
- Tags: CPython 3.10+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
682b928aa39d73dccdeed9a6574ab22f66424f3296cea86561795703107da50a
|
|
| MD5 |
70745610f60594ae5fb2010cec223397
|
|
| BLAKE2b-256 |
40173fb1599f98dd7c5f97e0211422a5784dc2099b21a888f105f6ff1bfff19e
|
Provenance
The following attestation bundles were made for archx-0.1.1-cp310-abi3-macosx_10_12_x86_64.whl:
Publisher:
publish.yaml on UnaryLab/archx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
archx-0.1.1-cp310-abi3-macosx_10_12_x86_64.whl -
Subject digest:
682b928aa39d73dccdeed9a6574ab22f66424f3296cea86561795703107da50a - Sigstore transparency entry: 2254449363
- Sigstore integration time:
-
Permalink:
UnaryLab/archx@7e514754d05999490975d74c7248f3d6b4e34bc3 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/UnaryLab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@7e514754d05999490975d74c7248f3d6b4e34bc3 -
Trigger Event:
release
-
Statement type: