mirror of
https://github.com/harvard-edge/cs249r_book.git
synced 2026-07-16 23:24:55 -05:00
- Complete the MLSYSIM -> MLSys.im display-name migration across mlsysim/docs, instructors, and shared config (code identifiers stay lowercase mlsysim) - Fix broken TinyTorch module links (_ABOUT.html -> .html) - Route the navbar Subscribe action to the newsletter page so Safari content blockers stop hiding the #subscribe anchor - Add the Accelerator Memory Tiers figure to compute_infrastructure with a registry-driven log-log capacity/bandwidth scatter - Add four sourced cloud accelerator specs (Groq LPU, Graphcore GC200, Untether speedAI240, d-Matrix Corsair) feeding the local-SRAM tier - Remove the unshipped Coming Soon audio-lectures placeholder and related Binder/audio references
473 lines
17 KiB
Plaintext
473 lines
17 KiB
Plaintext
---
|
|
title: "Contributing to MLSys·im"
|
|
subtitle: "Add hardware specs, write solvers, build tutorials, and grow the MLSys Zoo."
|
|
---
|
|
|
|
MLSys·im grows stronger with every new hardware spec, solver, tutorial, and bug report. This
|
|
guide explains how to contribute -- whether you are a student who spotted a wrong datasheet
|
|
number, an instructor designing a teaching scenario, or a researcher who needs a new
|
|
analytical solver.
|
|
|
|
::: {.callout-note}
|
|
## Before you start
|
|
|
|
MLSys·im is maintained as part of the [ML Systems textbook](https://mlsysbook.ai) project.
|
|
All contributions go through GitHub. If you are not familiar with Git and pull requests,
|
|
[GitHub's guide](https://docs.github.com/en/get-started/quickstart/contributing-to-projects)
|
|
is a good starting point.
|
|
|
|
**Repository:** [harvard-edge/cs249r_book]({{< var github_repo >}})
|
|
:::
|
|
|
|
---
|
|
|
|
## At a Glance
|
|
|
|
| Contribution | Difficulty | Impact | Where it lives |
|
|
|:---|:---:|:---|:---|
|
|
| Report a bug or wrong spec | Beginner | High -- specs affect all users | GitHub Issues |
|
|
| Add hardware to the Silicon Zoo | Intermediate | High -- expands coverage | `mlsysim/hardware/` |
|
|
| Add a model to the Model Zoo | Intermediate | Medium -- new workloads | `mlsysim/models/` |
|
|
| Add a fleet or fabric | Intermediate | Medium -- new topologies | `mlsysim/systems/` |
|
|
| Add a grid or rack profile | Intermediate | Medium -- new infra | `mlsysim/infrastructure/` |
|
|
| Write a tutorial | Intermediate | High -- improves learning | `docs/tutorials/` |
|
|
| Add or improve a solver | Advanced | High -- new analysis capabilities | `engine/solvers/` |
|
|
|
|
---
|
|
|
|
## 1. Reporting Issues
|
|
|
|
The fastest way to contribute: open an issue on GitHub.
|
|
|
|
**Good bug reports include:**
|
|
|
|
- Which spec is wrong (e.g., "A100 peak TFLOP/s in `Hardware.Cloud.A100`")
|
|
- The correct value and your source (official datasheet URL preferred)
|
|
- The version of MLSys·im you are using (`python -c "import mlsysim; print(mlsysim.__version__)"`)
|
|
|
|
**Good feature requests include:**
|
|
|
|
- What hardware, model, or solver you want added and why
|
|
- A link to the official specification or paper
|
|
|
|
---
|
|
|
|
## 2. Adding Hardware to the Silicon Zoo {#sec-hardware}
|
|
|
|
Every chip in the Silicon Zoo lives in one of five categories: `Cloud`, `Workstation`,
|
|
`Mobile`, `Edge`, or `Tiny`. Each entry follows a strict format with mandatory provenance
|
|
metadata.
|
|
|
|
::: {.callout-tip}
|
|
## Background reading
|
|
The [Hardware Acceleration](../../slides/vol1/11_hw_acceleration/) and
|
|
[Compute Infrastructure](../../slides/vol2/02_compute_infrastructure/) slide decks cover
|
|
the accelerator landscape and datasheet specs that feed into MLSys·im's hardware registry.
|
|
:::
|
|
|
|
### Step 1: Add a YAML spec under `hardware/data/`
|
|
|
|
Chip and board specs live in the **Silicon Zoo** — there is no shared constants
|
|
file to park them in (units live in `core/units.py`, physical constants in
|
|
`physics/constants.py`). Add one YAML file under the right tier, for
|
|
example `mlsysim/hardware/data/cloud/MyAccelerator.yaml`. The loader validates
|
|
the file against `HardwareNode` at import time and exposes it through the same
|
|
Python API (`Hardware.Cloud.MyAccelerator`).
|
|
|
|
```yaml
|
|
__key__: MyAccelerator
|
|
name: Example Accelerator
|
|
release_year: 2026
|
|
compute:
|
|
peak_flops: 312 TFLOPs / s
|
|
precision_flops:
|
|
fp32: 19.5 TFLOPs / s
|
|
int8: 624 TOPS
|
|
memory:
|
|
capacity: 80 GiB
|
|
bandwidth: 2039 GB / s
|
|
interconnect:
|
|
name: PCIe Gen4 x16
|
|
bandwidth: 32 GB / s
|
|
tdp: 400 W
|
|
metadata:
|
|
provenance:
|
|
kind: datasheet
|
|
ref: Example accelerator datasheet
|
|
url: https://...
|
|
verified: "2026-05-30"
|
|
```
|
|
|
|
Reuse shared records from `mlsysim/core/provenance_catalog.py` when several entries
|
|
share one source. See `mlsysim/PROVENANCE.md` and run
|
|
`python -m mlsysim.tools.audit_provenance --scope all --strict` before opening a PR.
|
|
|
|
The YAML data layer is intentionally strict: duplicate YAML keys, duplicate
|
|
`__key__` values, missing data directories, and unknown schema fields fail
|
|
loading. If the value is a technology-class reference, use `@tech:` rather than
|
|
copying a shared fact into many devices, for example
|
|
`latency: "@tech:Interconnect.NVLink.latency"`.
|
|
|
|
### Step 2: Verify with the registry contract tests
|
|
|
|
The loader contract and duplicate-spec gates run automatically:
|
|
`tests/test_registry_loader_contract.py` and
|
|
`tests/test_registry_no_duplicate_specs.py`. The legacy `core/constants.py`
|
|
junk drawer was deleted outright; `tests/test_constants_allowlist.py` enforces
|
|
that neither it nor a compat shim for it ever comes back.
|
|
|
|
### Step 3: Use the canonical path in downstream examples
|
|
|
|
Examples import `Hardware.Cloud.A100`, not `A100_FLOPS_FP16_TENSOR`. Downstream
|
|
content should use the same canonical registry paths as package tutorials.
|
|
|
|
### Provenance rules
|
|
|
|
Every registry entry requires `metadata.provenance` (`Provenance` model in
|
|
`core/provenance.py`). Use `kind` honestly: `datasheet`, `literature`, `estimate`
|
|
(needs `notes`), `convention`, or `illustrative`.
|
|
|
|
1. Link to an **official primary source** (manufacturer datasheet, not a blog post)
|
|
2. Set `verified` (YYYY-MM-DD) on datasheet and literature entries
|
|
3. State **which variant** in `ref` or `notes` (e.g., SXM5 vs. PCIe)
|
|
4. When a spec varies across SKUs, use the **most conservative published value** unless the
|
|
variant is specified in the node name
|
|
|
|
### Formatting for QMD and LEGO cells
|
|
|
|
Display helpers live in `mlsysim.fmt` — keep physics in `mlsysim.physics.*`:
|
|
|
|
| Helper | Use when |
|
|
|:-------|:---------|
|
|
| `fmt(q, precision=1)` | Human-readable quantities in prose |
|
|
| `fmt_int(n)` | Integer counts without spurious decimals |
|
|
| `check(condition, message)` | Assert invariants in tutorials and LEGO cells |
|
|
| `MarkdownStr` | Inline QMD values that must not be LaTeX-escaped |
|
|
|
|
Registry operands come from zoos; derived values from `mlsysim.physics.calc_*` or solvers.
|
|
|
|
---
|
|
|
|
## 3. Adding Models to the Model Zoo {#sec-models}
|
|
|
|
Models live in category YAML files under `mlsysim/models/data/`: `language.yaml`,
|
|
`vision.yaml`, `tiny.yaml`, `recommendation.yaml`, `statespace.yaml`, and
|
|
`generativevision.yaml`. Each entry includes a `__type__` tag selecting the
|
|
validated workload class (`TransformerWorkload`, `CNNWorkload`, `SSMWorkload`,
|
|
`DiffusionWorkload`, `SparseTransformerWorkload`, or plain `Workload`).
|
|
|
|
::: {.callout-tip}
|
|
## Background reading
|
|
The [Network Architectures](../../slides/vol1/06_nn_architectures/) and
|
|
[Neural Network Computation](../../slides/vol1/05_nn_computation/) slide decks explain the
|
|
architectural parameters (layers, heads, hidden dimensions) that define each workload.
|
|
:::
|
|
|
|
### Transformer workloads
|
|
|
|
```yaml
|
|
Llama3_8B:
|
|
__type__: TransformerWorkload
|
|
name: Llama-3.1-8B
|
|
architecture: Transformer
|
|
parameters: 8030000000 param
|
|
inference_flops: 16060000000 flop
|
|
layers: 32
|
|
hidden_dim: 4096
|
|
heads: 32
|
|
kv_heads: 8
|
|
```
|
|
|
|
For `inference_flops`, the standard approximation is $2P$ FLOPs per token for transformer
|
|
forward passes (multiply-accumulate counted as 2 operations). When a more precise count
|
|
is available from the paper, use it and note the source in a comment.
|
|
|
|
### CNN workloads
|
|
|
|
```yaml
|
|
ResNet50:
|
|
__type__: CNNWorkload
|
|
name: ResNet-50
|
|
architecture: CNN
|
|
parameters: 25600000 param
|
|
inference_flops: 4100000000 flop
|
|
layers: 50
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Adding Systems and Infrastructure {#sec-systems}
|
|
|
|
MLSys·im models the full deployment stack: individual accelerators compose into **nodes**,
|
|
nodes compose into **racks** and **fleets**, and fleets connect via **network fabrics**.
|
|
Infrastructure captures the **grid**, datacenter environment, pricing, and capacity
|
|
facts that those systems run within.
|
|
|
|
::: {.callout-tip}
|
|
## Background reading
|
|
The [Network Fabrics](../../slides/vol2/03_network_fabrics/) and
|
|
[Fleet Orchestration](../../slides/vol2/08_fleet_orchestration/) slide decks explain the
|
|
network topologies and cluster compositions that MLSys·im models analytically.
|
|
:::
|
|
|
|
### Adding a fleet or fabric (`systems/registry.py`)
|
|
|
|
```python
|
|
# A new reference node
|
|
DGX_B200 = Node(
|
|
name="DGX B200",
|
|
accelerator=Hardware.Cloud.B200,
|
|
accelerators_per_node=8,
|
|
intra_node_bw=1800 * ureg.GB / ureg.second,
|
|
nics_per_node=8,
|
|
)
|
|
|
|
# A new cluster built from that node
|
|
Training_2K = Fleet(
|
|
name="Training Cluster (2048 GPUs)",
|
|
node=DGX_B200,
|
|
count=256, # 256 nodes x 8 GPUs = 2048
|
|
fabric=Fabrics.InfiniBand_NDR,
|
|
)
|
|
```
|
|
|
|
### Adding a grid profile (`infrastructure/data/grids.yaml`)
|
|
|
|
Grid profiles capture the carbon intensity, cooling efficiency (PUE), and water usage
|
|
(WUE) of a datacenter region.
|
|
|
|
```yaml
|
|
Iceland:
|
|
name: Iceland (Geothermal)
|
|
carbon_intensity_g_kwh: 28
|
|
pue: 1.06
|
|
wue: 0.0
|
|
primary_source: geothermal
|
|
metadata:
|
|
provenance: "@prov:IEA_WEO_2023"
|
|
```
|
|
|
|
::: {.callout-tip}
|
|
## Background reading
|
|
The [Sustainable AI](../../slides/vol2/15_sustainable_ai/) slide deck covers PUE, WUE, and
|
|
carbon intensity -- the exact quantities that `GridProfile` captures.
|
|
:::
|
|
|
|
---
|
|
|
|
## 5. Writing a Tutorial {#sec-tutorials}
|
|
|
|
The best tutorials teach **one insight** through **one concrete example**. Before writing,
|
|
answer three questions:
|
|
|
|
1. **What is the one thing the reader will understand after this tutorial?**
|
|
2. **What would they have guessed incorrectly before reading it?**
|
|
3. **What surprising number will they compute?**
|
|
|
|
### Tutorial structure
|
|
|
|
Follow the pattern established in [Hello, Roofline](tutorials/00_hello_roofline.qmd),
|
|
[Geography is a Systems Variable](tutorials/07_geography.qmd),
|
|
[Two Phases of Inference](tutorials/02_two_phases.qmd), and
|
|
[Scaling to 1000 GPUs](tutorials/06_scaling_1000_gpus.qmd):
|
|
|
|
```markdown
|
|
---
|
|
title: "Short, specific title"
|
|
subtitle: "Payoff sentence: what you learn in 10 words."
|
|
---
|
|
|
|
[2-3 sentence hook: what problem does this solve?]
|
|
|
|
By the end of this tutorial you will understand:
|
|
- [Concept 1]
|
|
- [Concept 2]
|
|
- [Concept 3]
|
|
|
|
::: {.callout-tip}
|
|
## Background concept
|
|
[1-paragraph intuition before any code]
|
|
:::
|
|
|
|
## 1. Setup
|
|
[import block -- path hack MUST be hidden with #| echo: false]
|
|
|
|
## 2. First Example
|
|
[minimal working code + output]
|
|
|
|
## 3-N. Build Understanding
|
|
[progressive complexity, callouts explaining surprising results]
|
|
|
|
## What You Learned
|
|
[bullet list recap]
|
|
|
|
## Next Steps
|
|
[2-3 links to related content]
|
|
```
|
|
|
|
### Code style in tutorials
|
|
|
|
- **Use clean imports**: Start with `import mlsysim`. The package is `pip install`-ed in the docs build environment (see `.github/workflows/mlsysim-preview-dev.yml`), so no path manipulation is needed.
|
|
- **Use Zoo entries**: Pull from `mlsysim.Hardware.Cloud.A100`, `mlsysim.Models.Language.Llama3_70B`, etc. -- no hardcoded constants in tutorial code
|
|
- **Print with units**: Always use pint's `~` format spec: `f"{value.to('ms'):~.2f}"`
|
|
- **Comment sparingly**: Code should be readable without comments; add a callout if explanation is needed
|
|
|
|
### Linking to slide decks
|
|
|
|
When your tutorial covers a topic with an existing slide deck, link to it so readers can
|
|
deepen their understanding. Relevant slide decks for common tutorial topics:
|
|
|
|
| Tutorial topic | Slide deck |
|
|
|:---|:---|
|
|
| Roofline analysis | [Hardware Acceleration](../../slides/vol1/11_hw_acceleration/) |
|
|
| Benchmarking & MFU | [Benchmarking](../../slides/vol1/12_benchmarking/), [Performance Engineering](../../slides/vol2/09_performance_engineering/) |
|
|
| LLM serving (TTFT/ITL) | [Model Serving](../../slides/vol1/13_model_serving/), [Inference at Scale](../../slides/vol2/10_inference/) |
|
|
| Distributed training | [Model Training](../../slides/vol1/08_training/), [Distributed Training](../../slides/vol2/05_distributed_training/) |
|
|
| Collective communication | [Collective Communication](../../slides/vol2/06_collective_communication/) |
|
|
| Fault tolerance | [Fault Tolerance](../../slides/vol2/07_fault_tolerance/) |
|
|
| Sustainability & carbon | [Sustainable AI](../../slides/vol2/15_sustainable_ai/) |
|
|
| Model compression | [Model Compression](../../slides/vol1/10_model_compression/) |
|
|
| Network architectures | [Network Architectures](../../slides/vol1/06_nn_architectures/) |
|
|
|
|
---
|
|
|
|
## 6. Adding or Improving a Solver {#sec-solvers}
|
|
|
|
MLSys·im ships 32 analytical solvers (see `mlsysim.solvers`), each grounded in
|
|
peer-reviewed literature. All inherit from the 3-Tier base classes
|
|
(`ForwardModel`, `BaseSolver`, `BaseOptimizer`) and implement `solve(**kwargs)`.
|
|
The six foundational ones:
|
|
|
|
| Solver | What it computes | Key references |
|
|
|:---|:---|:---|
|
|
| `SingleNodeModel` | Roofline bounds, MFU/HFU | Williams et al. (2009) |
|
|
| `DistributedModel` | 3D/4D parallelism, all-reduce, pipeline bubbles | Shoeybi et al. (2019), Narayanan et al. (2019) |
|
|
| `ReliabilityModel` | MTBF, failure probability, Young-Daly checkpointing | Young (1974), Daly (2006) |
|
|
| `SustainabilityModel` | Energy, carbon, water (PUE, WUE) | Patterson et al. (2021) |
|
|
| `EconomicsModel` | CapEx, OpEx, TCO | Barroso et al. (2018) |
|
|
| `ServingModel` | TTFT, ITL, KV-cache pressure | Pope et al. (2023), Patel et al. (2024), Agrawal et al. (2024) |
|
|
|
|
::: {.callout-tip}
|
|
## Background reading
|
|
The [Performance Engineering](../../slides/vol2/09_performance_engineering/) and
|
|
[Distributed Training](../../slides/vol2/05_distributed_training/) slide decks cover
|
|
the analytical models (roofline, all-reduce cost, pipeline bubbles) that the solvers
|
|
implement.
|
|
:::
|
|
|
|
### Solver contribution checklist
|
|
|
|
1. **Place canonical equations in `mlsysim/physics/`** -- every solver equation must be
|
|
independently callable and unit-tested
|
|
2. **Inherit from `BaseSolver`** and implement `solve(**kwargs) -> dict`
|
|
3. **Use pint units throughout** -- all inputs and outputs must carry physical units
|
|
4. **Cite the source paper** in a docstring on the solver class
|
|
5. **Add tests** (e.g. in `tests/test_solver_invariants.py` or a new test file) covering at least one known-good result from the paper
|
|
6. **Document the solver** by adding a page under `docs/api/`
|
|
|
|
### Example: extending a solver
|
|
|
|
All formulas live in `mlsysim/physics/` so they can be tested in isolation:
|
|
|
|
```python
|
|
# In mlsysim/mlsysim/physics/
|
|
def ring_allreduce_time(message_bytes, num_nodes, bandwidth):
|
|
"""Ring all-reduce latency: 2(N-1)/N * M/B.
|
|
|
|
Reference: Thakur et al. (2005), "Optimization of Collective
|
|
Communication Operations in MPICH."
|
|
"""
|
|
return 2 * (num_nodes - 1) / num_nodes * message_bytes / bandwidth
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Running Tests
|
|
|
|
Before submitting a pull request, ensure the test suite passes:
|
|
|
|
```bash
|
|
# Install development dependencies
|
|
pip install -e ".[dev]"
|
|
|
|
# Run the full test suite (from the mlsysim package root)
|
|
pytest tests/ -v
|
|
|
|
# Run a specific test file
|
|
pytest tests/test_solver_invariants.py -v
|
|
```
|
|
|
|
Key areas of the test suite:
|
|
|
|
| Test file | What it validates |
|
|
|:---|:---|
|
|
| `test_engine.py` | Single-node inference, OOM exceptions, precision switching |
|
|
| `test_hardware.py` | Registry access, ridge point calculation, JSON serialization |
|
|
| `test_solver_invariants.py` / `test_solver_module_exports.py` | Solver behavior and the public `mlsysim.solvers` surface |
|
|
| `test_empirical.py` | Empirical validation against published numbers |
|
|
| `test_registry_loader_contract.py` / `test_constants_allowlist.py` | YAML loader contract and the retired-constants gate |
|
|
|
|
---
|
|
|
|
## 8. Submitting a Pull Request
|
|
|
|
1. **Fork** the repository on GitHub
|
|
2. **Create a branch** with a descriptive name: `git checkout -b feat/add-b200-hardware`
|
|
3. **Make your changes** following the patterns in this guide
|
|
4. **Run tests** to confirm nothing is broken
|
|
5. **Open a PR** against the `dev` branch with:
|
|
- A clear description of what changed and why
|
|
- A link to the source document for any new spec values
|
|
- Output showing your change working (`python -c "..."` snippet)
|
|
|
|
### Branch naming conventions
|
|
|
|
| Type | Pattern | Example |
|
|
|:---|:---|:---|
|
|
| New feature | `feat/<scope>` | `feat/add-mi300x-hardware` |
|
|
| Bug fix | `fix/<scope>` | `fix/a100-bandwidth-typo` |
|
|
| Documentation | `docs/<scope>` | `docs/tutorial-kv-cache` |
|
|
| Tests | `test/<scope>` | `test/reliability-solver` |
|
|
|
|
---
|
|
|
|
## 9. Architecture Overview
|
|
|
|
Understanding the module layout helps you find the right file to edit.
|
|
|
|
```
|
|
mlsysim/
|
|
core/
|
|
constants.py # Retired shim: re-exports units only (CI allowlist enforced)
|
|
loader.py # YAML loading, duplicate-key checks, registry generation
|
|
provenance.py # Sourced values and provenance helpers
|
|
registry/ # Base Registry pattern
|
|
types.py # Shared schema types
|
|
units.py # Unit registry and exported Pint units
|
|
engine/ # Solvers, scenario evaluation, calibration, explainers
|
|
physics/ # Canonical calc_* implementations (roofline, all-reduce, TCO, …)
|
|
hardware/data/ # Hardware.* YAML zoo
|
|
models/data/ # Models.* YAML zoo
|
|
datasets/data/ # Datasets.* YAML zoo
|
|
systems/registry.py # Systems.Nodes / Racks / Fabrics / Clusters / Storage / Pods
|
|
infrastructure/ # Infrastructure.* grids and pricing
|
|
scenarios/ # Runnable Scenarios.* bundles and ReferenceStats.* anchors
|
|
platforms/registry.py # Platforms.* zoo
|
|
tests/ # pytest suite (includes registry migration gates)
|
|
examples/ # Standalone scripts
|
|
docs/ # Quarto documentation site
|
|
```
|
|
|
|
## Community Standards
|
|
|
|
MLSys·im is a pedagogical tool used in courses at Harvard and beyond. Contributions should:
|
|
|
|
- **Prioritize accuracy over completeness** -- a wrong spec is worse than a missing one
|
|
- **Cite sources** -- every number needs a URL to an official datasheet or peer-reviewed paper
|
|
- **Explain the analytical reasoning** -- a tutorial that teaches *why* is better than one
|
|
that shows *how*
|
|
- **Use units everywhere** -- pint prevents dimensional errors; do not bypass it with raw floats
|
|
|
|
Thank you for helping make MLSys·im more accurate and useful for the next generation of
|
|
ML systems engineers.
|