mirror of
https://github.com/harvard-edge/cs249r_book.git
synced 2026-07-23 14:31:14 -05:00
2425 lines
113 KiB
HTML
2425 lines
113 KiB
HTML
<!DOCTYPE html>
|
||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
||
|
||
<meta charset="utf-8">
|
||
<meta name="generator" content="quarto-1.9.38">
|
||
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||
|
||
|
||
<title>Welcome – TinyTorch</title>
|
||
<style>
|
||
/* Default styles provided by pandoc.
|
||
** See https://pandoc.org/MANUAL.html#variables-for-html for config info.
|
||
*/
|
||
code{white-space: pre-wrap;}
|
||
span.smallcaps{font-variant: small-caps;}
|
||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||
div.column{flex: auto; overflow-x: auto;}
|
||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||
ul.task-list{list-style: none;}
|
||
ul.task-list li input[type="checkbox"] {
|
||
width: 0.8em;
|
||
margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */
|
||
vertical-align: middle;
|
||
}
|
||
</style>
|
||
|
||
|
||
<script src="site_libs/quarto-nav/quarto-nav.js"></script>
|
||
<script src="site_libs/clipboard/clipboard.min.js"></script>
|
||
<script src="site_libs/quarto-search/autocomplete.umd.js"></script>
|
||
<script src="site_libs/quarto-search/fuse.min.js"></script>
|
||
<script src="site_libs/quarto-search/quarto-search.js"></script>
|
||
<meta name="quarto:offset" content="./">
|
||
<link href="./big-picture.html" rel="next">
|
||
<link href="./assets/images/favicon.svg" rel="icon" type="image/svg+xml">
|
||
<script src="site_libs/quarto-html/quarto.js" type="module"></script>
|
||
<script src="site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
|
||
<script src="site_libs/quarto-html/popper.min.js"></script>
|
||
<script src="site_libs/quarto-html/tippy.umd.min.js"></script>
|
||
<script src="site_libs/quarto-html/anchor.min.js"></script>
|
||
<link href="site_libs/quarto-html/tippy.css" rel="stylesheet">
|
||
<link href="site_libs/quarto-html/quarto-syntax-highlighting-d58168542e1b05ab509c510cbeb13b13.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
|
||
<link href="site_libs/quarto-html/quarto-syntax-highlighting-dark-88e37a8f5ac5aee93fe4de4f1f74577c.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
|
||
<link href="site_libs/quarto-html/quarto-syntax-highlighting-d58168542e1b05ab509c510cbeb13b13.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
|
||
<script src="site_libs/bootstrap/bootstrap.min.js"></script>
|
||
<link href="site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
|
||
<link href="site_libs/bootstrap/bootstrap-2bab33dbe7817173bbc4a78ab485562b.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
|
||
<link href="site_libs/bootstrap/bootstrap-dark-41c6c8aaa029f41185ba15883681b9bb.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="light">
|
||
<link href="site_libs/bootstrap/bootstrap-2bab33dbe7817173bbc4a78ab485562b.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
|
||
<script id="quarto-search-options" type="application/json">{
|
||
"location": "navbar",
|
||
"copy-button": false,
|
||
"collapse-after": 3,
|
||
"panel-placement": "end",
|
||
"type": "overlay",
|
||
"limit": 50,
|
||
"keyboard-shortcut": [
|
||
"/"
|
||
],
|
||
"language": {
|
||
"search-no-results-text": "No results",
|
||
"search-matching-documents-text": "matching documents",
|
||
"search-copy-link-title": "Copy link to search",
|
||
"search-hide-matches-text": "Hide additional matches",
|
||
"search-more-match-text": "more match in this document",
|
||
"search-more-matches-text": "more matches in this document",
|
||
"search-clear-button-title": "Clear",
|
||
"search-text-placeholder": "",
|
||
"search-detached-cancel-button-title": "Cancel",
|
||
"search-submit-button-title": "Submit",
|
||
"search-label": "Search"
|
||
}
|
||
}</script>
|
||
<!-- Shared head includes — MLSysBook ecosystem -->
|
||
|
||
<!--
|
||
theme-persist (inline, sync) — applies stored color-scheme before first paint.
|
||
Inlined deliberately: runs before any other <script>, no extra round-trip,
|
||
and avoids per-subsite asset path differences. Canonical source:
|
||
shared/scripts/theme-persist.js (kept identical for documentation/testability).
|
||
If you change one, mirror the change to the other.
|
||
-->
|
||
<script>
|
||
(function () {
|
||
'use strict';
|
||
var STORAGE_KEY = 'quarto-color-scheme';
|
||
// Quarto's toggle writes 'alternate'/'default' (alternate = dark, the
|
||
// layered sheet); sibling non-Quarto sites write 'dark'/'light'. Both
|
||
// hit the same key, so we accept either. Quarto's own startup still
|
||
// checks `=== 'alternate'`, so we mirror onto <html> rather than rewrite.
|
||
function normalize(v) {
|
||
if (v === 'dark' || v === 'alternate') return 'dark';
|
||
if (v === 'light' || v === 'default') return 'light';
|
||
return null;
|
||
}
|
||
function preferredScheme() {
|
||
try {
|
||
var n = normalize(window.localStorage.getItem(STORAGE_KEY));
|
||
if (n) return n;
|
||
} catch (e) {}
|
||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||
return 'dark';
|
||
}
|
||
return 'light';
|
||
}
|
||
function apply(scheme) {
|
||
var html = document.documentElement;
|
||
if (!html) return;
|
||
html.setAttribute('data-bs-theme', scheme);
|
||
html.setAttribute('data-quarto-color-scheme', scheme);
|
||
html.style.colorScheme = scheme;
|
||
// Bridge to legacy `.quarto-dark` body class — about.css,
|
||
// community.css, and newsletter.css key their dark-mode CSS
|
||
// variables off `.quarto-dark { ... }`. Quarto's own toggle adds
|
||
// that class on click, but the OS-pref / first-paint path never
|
||
// does. Mirror the scheme onto body so those CSS variables fire
|
||
// on every dark path, not just toggle clicks. body may not exist
|
||
// yet on the first call (this script runs in <head>); a
|
||
// MutationObserver below catches it as soon as it parses.
|
||
var body = document.body;
|
||
if (body) body.classList.toggle('quarto-dark', scheme === 'dark');
|
||
}
|
||
apply(preferredScheme());
|
||
// Catch the FOUC window between <head> apply() and DOMContentLoaded:
|
||
// <body> may not exist yet at first apply(), but as soon as the
|
||
// parser appends it we want the legacy class bridge in place so any
|
||
// CSS keyed on `.quarto-dark` paints correctly on first render.
|
||
if (!document.body) {
|
||
var earlyObserver = new MutationObserver(function () {
|
||
if (document.body) {
|
||
apply(preferredScheme());
|
||
earlyObserver.disconnect();
|
||
}
|
||
});
|
||
earlyObserver.observe(document.documentElement, { childList: true });
|
||
}
|
||
// Quarto's toggle updates localStorage but not <html>, so wrap it to
|
||
// mirror the new value onto data-bs-theme; otherwise clicking the toggle
|
||
// leaves CSS keyed off [data-bs-theme="dark"] rendering against the wrong
|
||
// stylesheet until the next reload.
|
||
function syncFromStorage() {
|
||
try {
|
||
var n = normalize(window.localStorage.getItem(STORAGE_KEY));
|
||
if (n) apply(n);
|
||
} catch (e) {}
|
||
}
|
||
function wrapToggle() {
|
||
var orig = window.quartoToggleColorScheme;
|
||
if (typeof orig !== 'function' || orig.__mlsbWrapped) return;
|
||
var wrapped = function () { var r = orig.apply(this, arguments); syncFromStorage(); return r; };
|
||
wrapped.__mlsbWrapped = true;
|
||
window.quartoToggleColorScheme = wrapped;
|
||
}
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', function () { wrapToggle(); syncFromStorage(); });
|
||
} else {
|
||
wrapToggle(); syncFromStorage();
|
||
}
|
||
// Defend the legacy `.quarto-dark` body class against Quarto's own
|
||
// `toggleBodyColor(mode)`, which runs *after* this script and re-asserts
|
||
// the body class based on `mode` — and `mode` defaults to 'light' when
|
||
// there's no stored quarto-color-scheme value, even when the OS / first
|
||
// paint already resolved to dark via `data-bs-theme`. Without this
|
||
// observer, on every fresh visit Quarto would clobber our bridge and
|
||
// restore `.quarto-light`, leaving `.quarto-dark`-keyed CSS variables
|
||
// (about/community/newsletter pages) at their light-mode defaults
|
||
// against the dark `data-bs-theme="dark"` background.
|
||
function bridgeBody() {
|
||
var body = document.body;
|
||
if (!body) return;
|
||
var wantDark = document.documentElement.getAttribute('data-bs-theme') === 'dark';
|
||
if (wantDark && !body.classList.contains('quarto-dark')) {
|
||
body.classList.add('quarto-dark');
|
||
body.classList.remove('quarto-light');
|
||
} else if (!wantDark && body.classList.contains('quarto-dark')) {
|
||
body.classList.remove('quarto-dark');
|
||
body.classList.add('quarto-light');
|
||
}
|
||
}
|
||
function watchBody() {
|
||
if (!document.body) return;
|
||
bridgeBody();
|
||
var bodyObs = new MutationObserver(bridgeBody);
|
||
bodyObs.observe(document.body, { attributes: true, attributeFilter: ['class'] });
|
||
var htmlObs = new MutationObserver(bridgeBody);
|
||
htmlObs.observe(document.documentElement, { attributes: true, attributeFilter: ['data-bs-theme'] });
|
||
}
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', watchBody);
|
||
} else {
|
||
watchBody();
|
||
}
|
||
window.addEventListener('storage', function (ev) {
|
||
if (ev.key !== STORAGE_KEY) return;
|
||
var n = normalize(ev.newValue);
|
||
if (n) apply(n);
|
||
});
|
||
if (window.matchMedia) {
|
||
try {
|
||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function (ev) {
|
||
try { if (window.localStorage.getItem(STORAGE_KEY)) return; } catch (e) {}
|
||
apply(ev.matches ? 'dark' : 'light');
|
||
});
|
||
} catch (e) {}
|
||
}
|
||
})();
|
||
</script>
|
||
|
||
<!--
|
||
Build-stamp styling. Tiny, neutral, dark-mode aware. The actual stamp text
|
||
is injected by shared/scripts/inject-build-stamp.sh into footer markup
|
||
containing the literal MLSB_BUILD_STAMP HTML-comment token (see that
|
||
script for the exact pattern — we cannot write it here because HTML
|
||
comments cannot nest and the inner closer would terminate this block).
|
||
-->
|
||
<style>
|
||
.mlsb-build-stamp {
|
||
display: inline-block;
|
||
margin-top: 0.25rem;
|
||
font-size: 0.75rem;
|
||
opacity: 0.6;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
[data-bs-theme="dark"] .mlsb-build-stamp { opacity: 0.5; }
|
||
</style>
|
||
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||
<link rel="icon" href="https://mlsysbook.ai/vol1/assets/images/icons/favicon.png" type="image/png">
|
||
|
||
<!--
|
||
navbar-theme-toggle-relocate — moves the Quarto theme toggle into the
|
||
navbar's right-side .navbar-nav group at page load, so it collapses into
|
||
the hamburger menu alongside Subscribe/Star/Support/GitHub at narrow widths
|
||
instead of being stranded in the middle by Quarto's mx-auto brand layout.
|
||
|
||
Why JS: Quarto auto-injects the toggle into .quarto-navbar-tools (outside
|
||
.navbar-collapse). CSS can't move DOM nodes between containers, and CSS
|
||
positioning hacks (absolute/right: 50px) fight Bootstrap's responsive
|
||
layout below 992px. Moving the node once at startup is the standard
|
||
approach used across Quarto-based sites with the same problem.
|
||
-->
|
||
<script>
|
||
(function () {
|
||
'use strict';
|
||
function relocateThemeToggle() {
|
||
var tools = document.querySelector('.quarto-navbar-tools');
|
||
if (!tools) return;
|
||
var toggle = tools.querySelector('.quarto-color-scheme-toggle');
|
||
if (!toggle) return;
|
||
var navRight = document.querySelector(
|
||
'.navbar .navbar-collapse .navbar-nav.ms-auto'
|
||
) || document.querySelector(
|
||
'.navbar .navbar-collapse .navbar-nav:last-of-type'
|
||
);
|
||
if (!navRight) return;
|
||
var li = document.createElement('li');
|
||
li.className = 'nav-item navbar-theme-toggle-item';
|
||
toggle.classList.add('nav-link');
|
||
li.appendChild(toggle);
|
||
navRight.appendChild(li);
|
||
tools.style.display = 'none';
|
||
}
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', relocateThemeToggle);
|
||
} else {
|
||
relocateThemeToggle();
|
||
}
|
||
})();
|
||
</script>
|
||
|
||
<!--
|
||
navbar-brand-href-fix — force the navbar brand link to the ecosystem root
|
||
(https://mlsysbook.ai/) on every subsite.
|
||
|
||
Quarto sets each subsite's `site-url` to `https://mlsysbook.ai/<subsite>/`
|
||
and then relativizes any navbar.href value that lives inside the
|
||
site-url's domain. The shared `href: https://mlsysbook.ai/` in
|
||
navbar-common.yml therefore gets emitted as `./index.html`, which on
|
||
vol1/vol2/tinytorch/etc. resolves to *that subsite's* root rather than
|
||
the ecosystem landing page. Override the brand link href in JS after
|
||
Quarto's render: this is a one-line user-experience fix that does not
|
||
fight Quarto's URL machinery.
|
||
-->
|
||
<script>
|
||
(function () {
|
||
'use strict';
|
||
function fixBrandHref() {
|
||
var brand = document.querySelectorAll(
|
||
'.navbar .navbar-brand, .navbar .navbar-brand-logo'
|
||
);
|
||
for (var i = 0; i < brand.length; i++) {
|
||
brand[i].setAttribute('href', 'https://mlsysbook.ai/');
|
||
}
|
||
}
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', fixBrandHref);
|
||
} else {
|
||
fixBrandHref();
|
||
}
|
||
})();
|
||
</script>
|
||
<link rel="apple-touch-icon" href="./assets/images/logos/logo-tinytorch.png">
|
||
<meta name="theme-color" content="#D4740C">
|
||
<!-- Release identity (rendered into the footer pill below).
|
||
The publish workflow drops release-manifest.json at
|
||
/tinytorch/release-manifest.json before deploy; preview
|
||
and local renders silently no-op. -->
|
||
<meta name="release-manifest" content="/tinytorch/release-manifest.json">
|
||
|
||
|
||
<meta property="og:title" content="Welcome – TinyTorch">
|
||
<meta property="og:description" content="An interactive course for building machine learning systems from the ground up. Learn by implementing your own PyTorch-style framework with hands-on coding, real datasets, and production-ready practices.">
|
||
<meta property="og:image" content="https://mlsysbook.ai/tinytorch/assets/images/logos/logo-tinytorch.png">
|
||
<meta property="og:site_name" content="TinyTorch">
|
||
<meta property="og:locale" content="en_US">
|
||
<meta property="og:image:height" content="328">
|
||
<meta property="og:image:width" content="583">
|
||
<meta name="twitter:title" content="Welcome – TinyTorch">
|
||
<meta name="twitter:description" content="An interactive course for building machine learning systems from the ground up. Learn by implementing your own PyTorch-style framework with hands-on coding, real datasets, and production-ready practices.">
|
||
<meta name="twitter:image" content="https://mlsysbook.ai/tinytorch/assets/images/logos/logo-tinytorch.png">
|
||
<meta name="twitter:card" content="summary_large_image">
|
||
<meta name="twitter:image-height" content="328">
|
||
<meta name="twitter:image-width" content="583">
|
||
</head>
|
||
|
||
<body class="nav-sidebar floating nav-fixed quarto-light"><script id="quarto-html-before-body" type="application/javascript">
|
||
const toggleBodyColorMode = (bsSheetEl) => {
|
||
const mode = bsSheetEl.getAttribute("data-mode");
|
||
const bodyEl = window.document.querySelector("body");
|
||
if (mode === "dark") {
|
||
bodyEl.classList.add("quarto-dark");
|
||
bodyEl.classList.remove("quarto-light");
|
||
} else {
|
||
bodyEl.classList.add("quarto-light");
|
||
bodyEl.classList.remove("quarto-dark");
|
||
}
|
||
}
|
||
const toggleBodyColorPrimary = () => {
|
||
const bsSheetEl = window.document.querySelector("link#quarto-bootstrap:not([rel=disabled-stylesheet])");
|
||
if (bsSheetEl) {
|
||
toggleBodyColorMode(bsSheetEl);
|
||
}
|
||
}
|
||
const setColorSchemeToggle = (alternate) => {
|
||
const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
|
||
for (let i=0; i < toggles.length; i++) {
|
||
const toggle = toggles[i];
|
||
if (toggle) {
|
||
if (alternate) {
|
||
toggle.classList.add("alternate");
|
||
} else {
|
||
toggle.classList.remove("alternate");
|
||
}
|
||
}
|
||
}
|
||
};
|
||
const toggleColorMode = (alternate) => {
|
||
// Switch the stylesheets
|
||
const primaryStylesheets = window.document.querySelectorAll('link.quarto-color-scheme:not(.quarto-color-alternate)');
|
||
const alternateStylesheets = window.document.querySelectorAll('link.quarto-color-scheme.quarto-color-alternate');
|
||
manageTransitions('#quarto-margin-sidebar .nav-link', false);
|
||
if (alternate) {
|
||
// note: dark is layered on light, we don't disable primary!
|
||
enableStylesheet(alternateStylesheets);
|
||
for (const sheetNode of alternateStylesheets) {
|
||
if (sheetNode.id === "quarto-bootstrap") {
|
||
toggleBodyColorMode(sheetNode);
|
||
}
|
||
}
|
||
} else {
|
||
disableStylesheet(alternateStylesheets);
|
||
enableStylesheet(primaryStylesheets)
|
||
toggleBodyColorPrimary();
|
||
}
|
||
manageTransitions('#quarto-margin-sidebar .nav-link', true);
|
||
// Switch the toggles
|
||
setColorSchemeToggle(alternate)
|
||
// Hack to workaround the fact that safari doesn't
|
||
// properly recolor the scrollbar when toggling (#1455)
|
||
if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
|
||
manageTransitions("body", false);
|
||
window.scrollTo(0, 1);
|
||
setTimeout(() => {
|
||
window.scrollTo(0, 0);
|
||
manageTransitions("body", true);
|
||
}, 40);
|
||
}
|
||
}
|
||
const disableStylesheet = (stylesheets) => {
|
||
for (let i=0; i < stylesheets.length; i++) {
|
||
const stylesheet = stylesheets[i];
|
||
stylesheet.rel = 'disabled-stylesheet';
|
||
}
|
||
}
|
||
const enableStylesheet = (stylesheets) => {
|
||
for (let i=0; i < stylesheets.length; i++) {
|
||
const stylesheet = stylesheets[i];
|
||
if(stylesheet.rel !== 'stylesheet') { // for Chrome, which will still FOUC without this check
|
||
stylesheet.rel = 'stylesheet';
|
||
}
|
||
}
|
||
}
|
||
const manageTransitions = (selector, allowTransitions) => {
|
||
const els = window.document.querySelectorAll(selector);
|
||
for (let i=0; i < els.length; i++) {
|
||
const el = els[i];
|
||
if (allowTransitions) {
|
||
el.classList.remove('notransition');
|
||
} else {
|
||
el.classList.add('notransition');
|
||
}
|
||
}
|
||
}
|
||
const isFileUrl = () => {
|
||
return window.location.protocol === 'file:';
|
||
}
|
||
const hasAlternateSentinel = () => {
|
||
let styleSentinel = getColorSchemeSentinel();
|
||
if (styleSentinel !== null) {
|
||
return styleSentinel === "alternate";
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
const setStyleSentinel = (alternate) => {
|
||
const value = alternate ? "alternate" : "default";
|
||
if (!isFileUrl()) {
|
||
window.localStorage.setItem("quarto-color-scheme", value);
|
||
} else {
|
||
localAlternateSentinel = value;
|
||
}
|
||
}
|
||
const getColorSchemeSentinel = () => {
|
||
if (!isFileUrl()) {
|
||
const storageValue = window.localStorage.getItem("quarto-color-scheme");
|
||
return storageValue != null ? storageValue : localAlternateSentinel;
|
||
} else {
|
||
return localAlternateSentinel;
|
||
}
|
||
}
|
||
const toggleGiscusIfUsed = (isAlternate, darkModeDefault) => {
|
||
const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
|
||
const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
|
||
let newTheme = '';
|
||
if(authorPrefersDark) {
|
||
newTheme = isAlternate ? baseTheme : alternateTheme;
|
||
} else {
|
||
newTheme = isAlternate ? alternateTheme : baseTheme;
|
||
}
|
||
const changeGiscusTheme = () => {
|
||
// From: https://github.com/giscus/giscus/issues/336
|
||
const sendMessage = (message) => {
|
||
const iframe = document.querySelector('iframe.giscus-frame');
|
||
if (!iframe) return;
|
||
iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
|
||
}
|
||
sendMessage({
|
||
setConfig: {
|
||
theme: newTheme
|
||
}
|
||
});
|
||
}
|
||
const isGiscussLoaded = window.document.querySelector('iframe.giscus-frame') !== null;
|
||
if (isGiscussLoaded) {
|
||
changeGiscusTheme();
|
||
}
|
||
};
|
||
const authorPrefersDark = false;
|
||
const queryPrefersDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||
const darkModeDefault = queryPrefersDark.matches;
|
||
document.querySelector('link#quarto-text-highlighting-styles.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||
document.querySelector('link#quarto-bootstrap.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
|
||
let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default';
|
||
// Dark / light mode switch
|
||
window.quartoToggleColorScheme = () => {
|
||
// Read the current dark / light value
|
||
let toAlternate = !hasAlternateSentinel();
|
||
toggleColorMode(toAlternate);
|
||
setStyleSentinel(toAlternate);
|
||
toggleGiscusIfUsed(toAlternate, darkModeDefault);
|
||
window.dispatchEvent(new Event('resize'));
|
||
};
|
||
queryPrefersDark.addEventListener("change", e => {
|
||
if(window.localStorage.getItem("quarto-color-scheme") !== null)
|
||
return;
|
||
const alternate = e.matches
|
||
toggleColorMode(alternate);
|
||
localAlternateSentinel = e.matches ? 'alternate' : 'default'; // this is used alongside local storage!
|
||
toggleGiscusIfUsed(alternate, darkModeDefault);
|
||
});
|
||
// Switch to dark mode if need be
|
||
if (hasAlternateSentinel()) {
|
||
toggleColorMode(true);
|
||
} else {
|
||
toggleColorMode(false);
|
||
}
|
||
</script>
|
||
|
||
<div id="quarto-search-results"></div>
|
||
<header id="quarto-header" class="headroom fixed-top">
|
||
<nav class="navbar navbar-expand-xl " data-bs-theme="dark">
|
||
<div class="navbar-container container-fluid">
|
||
<div class="navbar-brand-container mx-auto">
|
||
<a href="./index.html" class="navbar-brand navbar-brand-logo">
|
||
<img src="./assets/images/logo.png" alt="" class="navbar-logo light-content">
|
||
<img src="./assets/images/logo.png" alt="" class="navbar-logo dark-content">
|
||
</a>
|
||
<a class="navbar-brand" href="./index.html">
|
||
<span class="navbar-title">Machine Learning Systems</span>
|
||
</a>
|
||
</div>
|
||
<div id="quarto-search" class="" title="Search"></div>
|
||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" role="menu" aria-expanded="false" aria-label="Toggle navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">
|
||
<span class="navbar-toggler-icon"></span>
|
||
</button>
|
||
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||
<ul class="navbar-nav navbar-nav-scroll me-auto">
|
||
<li class="nav-item dropdown ">
|
||
<a class="nav-link dropdown-toggle" href="#" id="nav-menu-tinytorch" role="link" data-bs-toggle="dropdown" aria-expanded="false">
|
||
<span class="menu-text">TinyTorch</span>
|
||
</a>
|
||
<ul class="dropdown-menu" aria-labelledby="nav-menu-tinytorch">
|
||
<li>
|
||
<a class="dropdown-item" href="./index.html"><i class="bi bi-fire" role="img">
|
||
</i>
|
||
<span class="dropdown-text">TinyTorch Home</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="./getting-started.html">
|
||
<span class="dropdown-text">Getting Started</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="./big-picture.html">
|
||
<span class="dropdown-text">Big Picture</span></a>
|
||
</li>
|
||
<li><hr class="dropdown-divider"></li>
|
||
<li>
|
||
<a class="dropdown-item" href="./tiers/foundation.html">
|
||
<span class="dropdown-text">Foundation Tier</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="./tiers/architecture.html">
|
||
<span class="dropdown-text">Architecture Tier</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="./tiers/optimization.html">
|
||
<span class="dropdown-text">Optimization Tier</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="./tiers/olympics.html">
|
||
<span class="dropdown-text">Torch Olympics</span></a>
|
||
</li>
|
||
<li><hr class="dropdown-divider"></li>
|
||
<li>
|
||
<a class="dropdown-item" href="./milestones/index.html">
|
||
<span class="dropdown-text">Historical Milestones</span></a>
|
||
</li>
|
||
<li><hr class="dropdown-divider"></li>
|
||
<li>
|
||
<a class="dropdown-item" href="./tito/overview.html">
|
||
<span class="dropdown-text">TITO CLI</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="./datasets.html">
|
||
<span class="dropdown-text">Datasets Guide</span></a>
|
||
</li>
|
||
<li><hr class="dropdown-divider"></li>
|
||
<li>
|
||
<a class="dropdown-item" href="./assets/downloads/TinyTorch-Guide.pdf" target="_blank"><i class="bi bi-file-pdf" role="img">
|
||
</i>
|
||
<span class="dropdown-text">TinyTorch Guide (PDF)</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="./assets/downloads/TinyTorch-Paper.pdf" target="_blank"><i class="bi bi-file-pdf" role="img">
|
||
</i>
|
||
<span class="dropdown-text">TinyTorch Paper (PDF)</span></a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="nav-item dropdown ">
|
||
<a class="nav-link dropdown-toggle" href="#" id="nav-menu-read" role="link" data-bs-toggle="dropdown" aria-expanded="false">
|
||
<span class="menu-text">Read</span>
|
||
</a>
|
||
<ul class="dropdown-menu" aria-labelledby="nav-menu-read">
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/vol1/"><i class="bi bi-journal" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Volume I: Foundations</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/vol2/"><i class="bi bi-journal" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Volume II: At Scale</span></a>
|
||
</li>
|
||
<li><hr class="dropdown-divider"></li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/vol1/assets/downloads/Machine-Learning-Systems-Vol1.pdf" target="_blank"><i class="bi bi-file-pdf" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Volume I PDF</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/vol1/assets/downloads/Machine-Learning-Systems-Vol1.epub" target="_blank"><i class="bi bi-journal-text" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Volume I EPUB</span></a>
|
||
</li>
|
||
<li><hr class="dropdown-divider"></li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/vol2/assets/downloads/Machine-Learning-Systems-Vol2.pdf" target="_blank"><i class="bi bi-file-pdf" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Volume II PDF</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/vol2/assets/downloads/Machine-Learning-Systems-Vol2.epub" target="_blank"><i class="bi bi-journal-text" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Volume II EPUB</span></a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="nav-item dropdown ">
|
||
<a class="nav-link dropdown-toggle" href="#" id="nav-menu-build" role="link" data-bs-toggle="dropdown" aria-expanded="false">
|
||
<span class="menu-text">Build</span>
|
||
</a>
|
||
<ul class="dropdown-menu" aria-labelledby="nav-menu-build">
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/labs/"><i class="bi bi-sliders" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Labs</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/tinytorch/"><i class="bi bi-fire" role="img">
|
||
</i>
|
||
<span class="dropdown-text">TinyTorch</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/kits/"><i class="bi bi-cpu" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Hardware Kits</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/mlsysim/"><i class="bi bi-calculator" role="img">
|
||
</i>
|
||
<span class="dropdown-text">MLSys·im</span></a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="nav-item dropdown ">
|
||
<a class="nav-link dropdown-toggle" href="#" id="nav-menu-teach" role="link" data-bs-toggle="dropdown" aria-expanded="false">
|
||
<span class="menu-text">Teach</span>
|
||
</a>
|
||
<ul class="dropdown-menu" aria-labelledby="nav-menu-teach">
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/instructors/course-map.html"><i class="bi bi-signpost-split" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Course Map</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/slides/"><i class="bi bi-easel" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Lecture Slides</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/instructors/"><i class="bi bi-person-video3" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Instructor Hub</span></a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="nav-item dropdown ">
|
||
<a class="nav-link dropdown-toggle" href="#" id="nav-menu-prepare" role="link" data-bs-toggle="dropdown" aria-expanded="false">
|
||
<span class="menu-text">Prepare</span>
|
||
</a>
|
||
<ul class="dropdown-menu" aria-labelledby="nav-menu-prepare">
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/staffml/"><i class="bi bi-mortarboard" role="img">
|
||
</i>
|
||
<span class="dropdown-text">StaffML</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/staffml/plans"><i class="bi bi-map" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Study Plans</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/staffml/gauntlet"><i class="bi bi-lightning" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Gauntlet Mode</span></a>
|
||
</li>
|
||
<li><hr class="dropdown-divider"></li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/staffml/downloads/StaffML-Paper.pdf" target="_blank"><i class="bi bi-file-pdf" role="img">
|
||
</i>
|
||
<span class="dropdown-text">StaffML Paper</span></a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="nav-item dropdown ">
|
||
<a class="nav-link dropdown-toggle" href="#" id="nav-menu-connect" role="link" data-bs-toggle="dropdown" aria-expanded="false">
|
||
<span class="menu-text">Connect</span>
|
||
</a>
|
||
<ul class="dropdown-menu" aria-labelledby="nav-menu-connect">
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/newsletter/"><i class="bi bi-envelope" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Newsletter</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/community/"><i class="bi bi-globe" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Global Network</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/community/events.html"><i class="bi bi-calendar-event" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Workshops & Events</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/community/partners.html"><i class="bi bi-people" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Partners & Sponsors</span></a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="nav-item dropdown ">
|
||
<a class="nav-link dropdown-toggle" href="#" id="nav-menu-about" role="link" data-bs-toggle="dropdown" aria-expanded="false">
|
||
<span class="menu-text">About</span>
|
||
</a>
|
||
<ul class="dropdown-menu" aria-labelledby="nav-menu-about">
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/about/"><i class="bi bi-bullseye" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Mission</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/about/#story"><i class="bi bi-book" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Our Story</span></a>
|
||
</li>
|
||
<li><hr class="dropdown-divider"></li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/about/people.html"><i class="bi bi-person-lines-fill" role="img">
|
||
</i>
|
||
<span class="dropdown-text">People</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/about/contributors.html"><i class="bi bi-people" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Contributors</span></a>
|
||
</li>
|
||
<li><hr class="dropdown-divider"></li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://mlsysbook.ai/about/license.html"><i class="bi bi-cc-circle" role="img">
|
||
</i>
|
||
<span class="dropdown-text">License</span></a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul class="navbar-nav navbar-nav-scroll ms-auto">
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="./#subscribe"> <i class="bi bi-envelope" role="img">
|
||
</i>
|
||
<span class="menu-text">Subscribe</span></a>
|
||
</li>
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="https://github.com/harvard-edge/cs249r_book" target="_blank"> <i class="bi bi-star" role="img">
|
||
</i>
|
||
<span class="menu-text">Star</span></a>
|
||
</li>
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="https://opencollective.com/mlsysbook" target="_blank"> <i class="bi bi-heart" role="img">
|
||
</i>
|
||
<span class="menu-text">Support</span></a>
|
||
</li>
|
||
<li class="nav-item dropdown ">
|
||
<a class="nav-link dropdown-toggle" href="#" id="nav-menu-github" role="link" data-bs-toggle="dropdown" aria-expanded="false">
|
||
<i class="bi bi-github" role="img">
|
||
</i>
|
||
<span class="menu-text">GitHub</span>
|
||
</a>
|
||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="nav-menu-github">
|
||
<li>
|
||
<a class="dropdown-item" href="https://github.com/harvard-edge/cs249r_book/discussions" target="_blank"><i class="bi bi-chat" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Discussions</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://github.com/harvard-edge/cs249r_book" target="_blank"><i class="bi bi-pencil" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Edit this page</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://github.com/harvard-edge/cs249r_book/issues/new" target="_blank"><i class="bi bi-bug" role="img">
|
||
</i>
|
||
<span class="dropdown-text">Report an issue</span></a>
|
||
</li>
|
||
<li>
|
||
<a class="dropdown-item" href="https://github.com/harvard-edge/cs249r_book" target="_blank"><i class="bi bi-code" role="img">
|
||
</i>
|
||
<span class="dropdown-text">View source</span></a>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</div> <!-- /navcollapse -->
|
||
<div class="quarto-navbar-tools">
|
||
<a href="" class="quarto-color-scheme-toggle quarto-navigation-tool px-1" onclick="window.quartoToggleColorScheme(); return false;" title="Toggle dark mode"><i class="bi"></i></a>
|
||
</div>
|
||
</div> <!-- /container-fluid -->
|
||
</nav>
|
||
<nav class="quarto-secondary-nav">
|
||
<div class="container-fluid d-flex">
|
||
<button type="button" class="quarto-btn-toggle btn" data-bs-toggle="collapse" role="button" data-bs-target=".quarto-sidebar-collapse-item" aria-controls="quarto-sidebar" aria-expanded="false" aria-label="Toggle sidebar navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">
|
||
<i class="bi bi-layout-text-sidebar-reverse"></i>
|
||
</button>
|
||
<nav class="quarto-page-breadcrumbs" aria-label="breadcrumb"><ol class="breadcrumb"><li class="breadcrumb-item"><a href="./preface.html">🚀 Getting Started</a></li><li class="breadcrumb-item"><a href="./preface.html">Welcome</a></li></ol></nav>
|
||
<a class="flex-grow-1" role="navigation" data-bs-toggle="collapse" data-bs-target=".quarto-sidebar-collapse-item" aria-controls="quarto-sidebar" aria-expanded="false" aria-label="Toggle sidebar navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">
|
||
</a>
|
||
</div>
|
||
</nav>
|
||
<div id="quarto-announcement" data-announcement-id="c1dc8b193ceca4e572bc367803d37925" class="alert alert-primary hidden"><i class="bi bi-megaphone quarto-announcement-icon"></i><div class="quarto-announcement-content">
|
||
<p>🔥 <strong>TinyTorch</strong> — build your own ML framework from scratch; the companion framework to the textbook.<br> 📘 <strong>The book:</strong> <a href="https://mlsysbook.ai/vol1/">Vol I: Foundations</a> · <a href="https://mlsysbook.ai/vol2/">Vol II: At Scale</a> — open access, free forever.<br> 🛠️ <strong>Alongside the book:</strong> <a href="https://mlsysbook.ai/kits/">Hardware Kits</a> (deploy) · <a href="https://mlsysbook.ai/mlsysim/">MLSys·im</a> (model) · <a href="https://mlsysbook.ai/labs/">Labs</a> (explore) · <a href="https://mlsysbook.ai/staffml/">StaffML</a> (practice)<br> 📬 <strong>Newsletter:</strong> ML Systems insights & updates — <a href="https://mlsysbook.ai/newsletter/">Subscribe →</a></p>
|
||
</div><i class="bi bi-x-lg quarto-announcement-action"></i></div>
|
||
</header>
|
||
<!-- content -->
|
||
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar">
|
||
<!-- sidebar -->
|
||
<nav id="quarto-sidebar" class="sidebar collapse collapse-horizontal quarto-sidebar-collapse-item sidebar-navigation floating overflow-auto">
|
||
<div class="pt-lg-2 mt-2 text-left sidebar-header">
|
||
<a href="./index.html" class="sidebar-logo-link">
|
||
<img src="./assets/images/logos/logo-tinytorch-transparent.png" alt="" class="sidebar-logo light-content py-0 d-lg-inline d-none">
|
||
<img src="./assets/images/logos/logo-tinytorch-transparent.png" alt="" class="sidebar-logo dark-content py-0 d-lg-inline d-none">
|
||
</a>
|
||
</div>
|
||
<div class="sidebar-menu-container">
|
||
<ul class="list-unstyled mt-1">
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./index.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">TinyTorch Home</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="px-0"><hr class="sidebar-divider hi "></li>
|
||
<li class="sidebar-item sidebar-item-section">
|
||
<div class="sidebar-item-container">
|
||
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-1" role="navigation" aria-expanded="true">
|
||
<span class="menu-text">🚀 Getting Started</span></a>
|
||
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-1" role="navigation" aria-expanded="true" aria-label="Toggle section">
|
||
<i class="bi bi-chevron-right ms-2"></i>
|
||
</a>
|
||
</div>
|
||
<ul id="quarto-sidebar-section-1" class="collapse list-unstyled sidebar-section depth1 show">
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./preface.html" class="sidebar-item-text sidebar-link active">
|
||
<span class="menu-text">Welcome</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./big-picture.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">Big Picture</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./getting-started.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">Quick Start</span></a>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="sidebar-item sidebar-item-section">
|
||
<div class="sidebar-item-container">
|
||
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-2" role="navigation" aria-expanded="true">
|
||
<span class="menu-text">🏗 Foundation Tier</span></a>
|
||
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-2" role="navigation" aria-expanded="true" aria-label="Toggle section">
|
||
<i class="bi bi-chevron-right ms-2"></i>
|
||
</a>
|
||
</div>
|
||
<ul id="quarto-sidebar-section-2" class="collapse list-unstyled sidebar-section depth1 show">
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./tiers/foundation.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">📖 Tier Overview</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/01_tensor.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">01. Tensor</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/02_activations.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">02. Activations</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/03_layers.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">03. Layers</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/04_losses.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">04. Losses</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/05_dataloader.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">05. DataLoader</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/06_autograd.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">06. Autograd</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/07_optimizers.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">07. Optimizers</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/08_training.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">08. Training</span></a>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="sidebar-item sidebar-item-section">
|
||
<div class="sidebar-item-container">
|
||
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-3" role="navigation" aria-expanded="true">
|
||
<span class="menu-text">🏛️ Architecture Tier</span></a>
|
||
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-3" role="navigation" aria-expanded="true" aria-label="Toggle section">
|
||
<i class="bi bi-chevron-right ms-2"></i>
|
||
</a>
|
||
</div>
|
||
<ul id="quarto-sidebar-section-3" class="collapse list-unstyled sidebar-section depth1 show">
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./tiers/architecture.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">📖 Tier Overview</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/09_convolutions.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">09. Convolutions</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/10_tokenization.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">10. Tokenization</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/11_embeddings.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">11. Embeddings</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/12_attention.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">12. Attention</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/13_transformers.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">13. Transformers</span></a>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="sidebar-item sidebar-item-section">
|
||
<div class="sidebar-item-container">
|
||
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-4" role="navigation" aria-expanded="true">
|
||
<span class="menu-text">⏱️ Optimization Tier</span></a>
|
||
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-4" role="navigation" aria-expanded="true" aria-label="Toggle section">
|
||
<i class="bi bi-chevron-right ms-2"></i>
|
||
</a>
|
||
</div>
|
||
<ul id="quarto-sidebar-section-4" class="collapse list-unstyled sidebar-section depth1 show">
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./tiers/optimization.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">📖 Tier Overview</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/14_profiling.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">14. Profiling</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/15_quantization.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">15. Quantization</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/16_compression.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">16. Compression</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/17_acceleration.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">17. Acceleration</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/18_memoization.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">18. Memoization</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/19_benchmarking.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">19. Benchmarking</span></a>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="sidebar-item sidebar-item-section">
|
||
<div class="sidebar-item-container">
|
||
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-5" role="navigation" aria-expanded="true">
|
||
<span class="menu-text">🏅 Capstone</span></a>
|
||
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-5" role="navigation" aria-expanded="true" aria-label="Toggle section">
|
||
<i class="bi bi-chevron-right ms-2"></i>
|
||
</a>
|
||
</div>
|
||
<ul id="quarto-sidebar-section-5" class="collapse list-unstyled sidebar-section depth1 show">
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./tiers/olympics.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">📖 Competition Overview</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./modules/20_capstone.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">20. Torch Olympics</span></a>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="sidebar-item sidebar-item-section">
|
||
<div class="sidebar-item-container">
|
||
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-6" role="navigation" aria-expanded="true">
|
||
<span class="menu-text">🎓 Conclusion</span></a>
|
||
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-6" role="navigation" aria-expanded="true" aria-label="Toggle section">
|
||
<i class="bi bi-chevron-right ms-2"></i>
|
||
</a>
|
||
</div>
|
||
<ul id="quarto-sidebar-section-6" class="collapse list-unstyled sidebar-section depth1 show">
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./conclusion.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">You Built Something Real</span></a>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="sidebar-item sidebar-item-section">
|
||
<div class="sidebar-item-container">
|
||
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-7" role="navigation" aria-expanded="true">
|
||
<span class="menu-text">🛠️ TITO CLI</span></a>
|
||
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-7" role="navigation" aria-expanded="true" aria-label="Toggle section">
|
||
<i class="bi bi-chevron-right ms-2"></i>
|
||
</a>
|
||
</div>
|
||
<ul id="quarto-sidebar-section-7" class="collapse list-unstyled sidebar-section depth1 show">
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./tito/overview.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">Command Overview</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./tito/modules.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">Module Workflow</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./tito/milestones.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">Milestone System</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./tito/data.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">Progress & Data</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./tito/testing.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">Developer Testing</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./tito/troubleshooting.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">Troubleshooting</span></a>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="sidebar-item sidebar-item-section">
|
||
<div class="sidebar-item-container">
|
||
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-8" role="navigation" aria-expanded="true">
|
||
<span class="menu-text">📚 Reference</span></a>
|
||
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-8" role="navigation" aria-expanded="true" aria-label="Toggle section">
|
||
<i class="bi bi-chevron-right ms-2"></i>
|
||
</a>
|
||
</div>
|
||
<ul id="quarto-sidebar-section-8" class="collapse list-unstyled sidebar-section depth1 show">
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./datasets.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">Datasets Guide</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./resources.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">Learning Resources</span></a>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li class="sidebar-item sidebar-item-section">
|
||
<div class="sidebar-item-container">
|
||
<a class="sidebar-item-text sidebar-link text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-9" role="navigation" aria-expanded="true">
|
||
<span class="menu-text">🤝 Community</span></a>
|
||
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-9" role="navigation" aria-expanded="true" aria-label="Toggle section">
|
||
<i class="bi bi-chevron-right ms-2"></i>
|
||
</a>
|
||
</div>
|
||
<ul id="quarto-sidebar-section-9" class="collapse list-unstyled sidebar-section depth1 show">
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./team.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">Team</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./community.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">Ecosystem</span></a>
|
||
</div>
|
||
</li>
|
||
<li class="sidebar-item">
|
||
<div class="sidebar-item-container">
|
||
<a href="./credits.html" class="sidebar-item-text sidebar-link">
|
||
<span class="menu-text">Acknowledgments</span></a>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</nav>
|
||
<div id="quarto-sidebar-glass" class="quarto-sidebar-collapse-item" data-bs-toggle="collapse" data-bs-target=".quarto-sidebar-collapse-item"></div>
|
||
<!-- margin-sidebar -->
|
||
<div id="quarto-margin-sidebar" class="sidebar margin-sidebar">
|
||
<nav id="TOC" role="doc-toc" class="toc-active">
|
||
<h2 id="toc-title">On this page</h2>
|
||
|
||
<ul>
|
||
<li><a href="#the-problem" id="toc-the-problem" class="nav-link active" data-scroll-target="#the-problem">The Problem</a></li>
|
||
<li><a href="#the-solution-ai-bricks" id="toc-the-solution-ai-bricks" class="nav-link" data-scroll-target="#the-solution-ai-bricks">The Solution: AI Bricks</a></li>
|
||
<li><a href="#who-this-is-for" id="toc-who-this-is-for" class="nav-link" data-scroll-target="#who-this-is-for">Who This Is For</a></li>
|
||
<li><a href="#what-you-need-to-start" id="toc-what-you-need-to-start" class="nav-link" data-scroll-target="#what-you-need-to-start">What You Need to Start</a></li>
|
||
<li><a href="#what-you-will-build" id="toc-what-you-will-build" class="nav-link" data-scroll-target="#what-you-will-build">What You Will Build</a></li>
|
||
<li><a href="#how-to-learn" id="toc-how-to-learn" class="nav-link" data-scroll-target="#how-to-learn">How to Learn</a></li>
|
||
<li><a href="#the-bigger-picture" id="toc-the-bigger-picture" class="nav-link" data-scroll-target="#the-bigger-picture">The Bigger Picture</a></li>
|
||
<li><a href="#for-instructors" id="toc-for-instructors" class="nav-link" data-scroll-target="#for-instructors">For Instructors</a></li>
|
||
<li><a href="#make-it-better" id="toc-make-it-better" class="nav-link" data-scroll-target="#make-it-better">Make It Better</a></li>
|
||
<li><a href="#whats-next" id="toc-whats-next" class="nav-link" data-scroll-target="#whats-next">What’s Next?</a></li>
|
||
</ul>
|
||
</nav>
|
||
</div>
|
||
<!-- main -->
|
||
<main class="content" id="quarto-document-content">
|
||
|
||
|
||
<header id="title-block-header" class="quarto-title-block default"><nav class="quarto-page-breadcrumbs quarto-title-breadcrumbs d-none d-lg-block" aria-label="breadcrumb"><ol class="breadcrumb"><li class="breadcrumb-item"><a href="./preface.html">🚀 Getting Started</a></li><li class="breadcrumb-item"><a href="./preface.html">Welcome</a></li></ol></nav>
|
||
<div class="quarto-title">
|
||
<h1 class="title">Welcome</h1>
|
||
</div>
|
||
|
||
|
||
|
||
<div class="quarto-title-meta">
|
||
|
||
|
||
|
||
|
||
</div>
|
||
|
||
|
||
|
||
</header>
|
||
|
||
|
||
<div style="text-align: center; margin: 1rem 0 2rem 0;">
|
||
<p><img src="assets/images/tito.png" alt="TinyTorch" style="width: 100%;"></p>
|
||
</div>
|
||
<p>Everyone wants to be an astronaut. Very few want to be the rocket scientist.</p>
|
||
<p>Machine learning is no different. Everyone wants to train models, run inference, deploy AI. Few want to understand how the frameworks actually work. Fewer still want to build one.</p>
|
||
<p>The world has plenty of users. It does not have enough builders: people who can debug, optimize, and adapt systems when the black box breaks down.</p>
|
||
<p>TinyTorch is for the builders.</p>
|
||
<section id="the-problem" class="level2">
|
||
<h2 class="anchored" data-anchor-id="the-problem">The Problem</h2>
|
||
<p>Most people can use PyTorch or TensorFlow. They can import libraries, call functions, train models. But very few understand how these frameworks work: how memory is managed for tensors, how autograd builds computation graphs, how optimizers update parameters. And almost no one has a guided, structured way to learn that from the ground up.</p>
|
||
<div class="callout callout-style-default callout-note callout-titled">
|
||
<div class="callout-header d-flex align-content-center">
|
||
<div class="callout-icon-container">
|
||
<i class="callout-icon"></i>
|
||
</div>
|
||
<div class="callout-title-container flex-fill">
|
||
Note
|
||
</div>
|
||
</div>
|
||
<div class="callout-body-container callout-body">
|
||
<p><strong>Why does this matter?</strong> Because users hit walls that builders do not:</p>
|
||
<ul>
|
||
<li>When your model runs out of memory, you need to understand <strong>tensor allocation</strong></li>
|
||
<li>When gradients explode, you need to understand the <strong>computation graph</strong></li>
|
||
<li>When training is slow, you need to understand where the <strong>bottlenecks</strong> are</li>
|
||
<li>When deploying on a microcontroller, you need to know what can be <strong>stripped away</strong></li>
|
||
</ul>
|
||
<p>The framework becomes a black box you cannot debug, optimize, or adapt. You are stuck waiting for someone else to solve your problem.</p>
|
||
</div>
|
||
</div>
|
||
<p>Students cannot learn this from production code. PyTorch is too large, too complex, too optimized. Fifty thousand lines of C++ across hundreds of files. No one learns to build rockets by studying the Saturn V.</p>
|
||
<p>They also cannot learn it from toy scripts. A hundred-line neural network does not reveal the architecture of a framework. It hides it.</p>
|
||
</section>
|
||
<section id="the-solution-ai-bricks" class="level2">
|
||
<h2 class="anchored" data-anchor-id="the-solution-ai-bricks">The Solution: AI Bricks</h2>
|
||
<p>TinyTorch teaches you the <strong>AI bricks</strong>: the stable engineering foundations you can use to build any AI system. Small enough to learn from: bite-sized code that runs even on a Raspberry Pi. Big enough to matter: showing the real architecture of how frameworks are built.</p>
|
||
<div class="who-grid">
|
||
<div class="who-card" style="border-left: 4px solid #1976d2;">
|
||
<p><strong>📖 MLSysBook</strong></p>
|
||
<p>
|
||
The <a href="https://mlsysbook.ai">Machine Learning Systems</a> textbook teaches you the <em>concepts</em> of the rocket ship: propulsion, guidance, life support.
|
||
</p>
|
||
</div>
|
||
<div class="who-card" style="border-left: 4px solid #ff8247;">
|
||
<p><strong>TinyTorch</strong></p>
|
||
<p>
|
||
TinyTorch is where you actually <em>build</em> a small rocket with your own hands. Not a toy. A real framework.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<p>This is how you move from <em>using</em> machine learning to <em>engineering</em> it: from running code in a notebook to designing the systems that run underneath.</p>
|
||
</section>
|
||
<section id="who-this-is-for" class="level2">
|
||
<h2 class="anchored" data-anchor-id="who-this-is-for">Who This Is For</h2>
|
||
<div class="who-grid">
|
||
<div class="who-card" style="border-left: 4px solid #9c27b0;">
|
||
<p><strong>Students & Researchers</strong></p>
|
||
<p>
|
||
Want to understand ML systems deeply, not just use them superficially. If you have wondered “how does that actually work?”, this is for you.
|
||
</p>
|
||
</div>
|
||
<div class="who-card" style="border-left: 4px solid #4caf50;">
|
||
<p><strong>ML Engineers</strong></p>
|
||
<p>
|
||
Need to debug, optimize, and deploy models in production. Understanding the systems underneath makes you more effective.
|
||
</p>
|
||
</div>
|
||
<div class="who-card" style="border-left: 4px solid #2196f3;">
|
||
<p><strong>Systems Programmers</strong></p>
|
||
<p>
|
||
You understand memory hierarchies, computational complexity, performance optimization. You want to apply it to ML.
|
||
</p>
|
||
</div>
|
||
<div class="who-card" style="border-left: 4px solid #ffc107;">
|
||
<p><strong>Self-taught Engineers</strong></p>
|
||
<p>
|
||
Can use frameworks but want to know how they work. Preparing for ML infrastructure roles and need systems-level understanding.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<p>What you need is not another API tutorial. You need to build.</p>
|
||
</section>
|
||
<section id="what-you-need-to-start" class="level2">
|
||
<h2 class="anchored" data-anchor-id="what-you-need-to-start">What You Need to Start</h2>
|
||
<p>You do not need to be a machine learning expert, and you do not need to have built a framework before. You need three things.</p>
|
||
<div class="who-grid">
|
||
<div class="who-card" style="border-left: 4px solid #1976d2;">
|
||
<p><strong>Python</strong></p>
|
||
<p>
|
||
If you can read and write a function, a loop, and a class, you have enough. There is no C++, no CUDA, no assembly. Everything sits on NumPy, and you will pick up the NumPy you need as you go.
|
||
</p>
|
||
</div>
|
||
<div class="who-card" style="border-left: 4px solid #4caf50;">
|
||
<p><strong>The math you already have</strong></p>
|
||
<p>
|
||
Vectors, matrices, and the chain rule from first-year calculus. That is the whole list. No measure theory, no convex optimization, no proofs. When a derivative shows up, we derive it in code, not on a chalkboard.
|
||
</p>
|
||
</div>
|
||
<div class="who-card" style="border-left: 4px solid #ff8247;">
|
||
<p><strong>A machine that turns on</strong></p>
|
||
<p>
|
||
TinyTorch runs on a laptop. It runs on a Raspberry Pi. The code is small on purpose, so you can hold a module in your head and run it on hardware you already own. No GPU, no cloud account, no four-figure compute bill.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<p>If you have used PyTorch and felt like a tourist, this is the ground you were standing on.</p>
|
||
</section>
|
||
<section id="what-you-will-build" class="level2">
|
||
<h2 class="anchored" data-anchor-id="what-you-will-build">What You Will Build</h2>
|
||
<p>By the end of TinyTorch, you will have implemented:</p>
|
||
<ul>
|
||
<li>A tensor library with broadcasting, reshaping, and matrix operations</li>
|
||
<li>Activation functions with numerical stability considerations</li>
|
||
<li>Neural network layers: linear, convolutional, normalization</li>
|
||
<li>An autograd engine that builds computation graphs and computes gradients</li>
|
||
<li>Optimizers that update parameters using those gradients</li>
|
||
<li>Data loaders that handle batching, shuffling, and preprocessing</li>
|
||
<li>A complete training loop that ties everything together</li>
|
||
<li>Tokenizers, embeddings, attention, and transformer architectures</li>
|
||
<li>Profiling, quantization, and optimization techniques</li>
|
||
</ul>
|
||
<p>Not a simulation. The actual architecture of modern ML frameworks, implemented at a scale you can hold in your head.</p>
|
||
</section>
|
||
<section id="how-to-learn" class="level2">
|
||
<h2 class="anchored" data-anchor-id="how-to-learn">How to Learn</h2>
|
||
<p>Each module follows a <strong>Build-Use-Reflect</strong> cycle: implement from scratch, apply to real problems, then connect what you built to production systems and understand the tradeoffs. Work through Foundation first, then choose your path based on your interests.</p>
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin: 1.5rem 0;">
|
||
<div style="border: 1px solid #e0e0e0; padding: 1rem; border-radius: 0.5rem;">
|
||
<p><strong>Type every line yourself</strong></p>
|
||
<p style="margin: 0.5rem 0 0 0; font-size: 0.9rem; color: #666;">
|
||
Do not copy-paste. The learning happens in the struggle of implementation.
|
||
</p>
|
||
</div>
|
||
<div style="border: 1px solid #e0e0e0; padding: 1rem; border-radius: 0.5rem;">
|
||
<p><strong>Profile your code</strong></p>
|
||
<p style="margin: 0.5rem 0 0 0; font-size: 0.9rem; color: #666;">
|
||
Use built-in profiling tools. Measure first, optimize second.
|
||
</p>
|
||
</div>
|
||
<div style="border: 1px solid #e0e0e0; padding: 1rem; border-radius: 0.5rem;">
|
||
<p><strong>Run the tests</strong></p>
|
||
<p style="margin: 0.5rem 0 0 0; font-size: 0.9rem; color: #666;">
|
||
Every module ships with tests. When they pass, you have built something real.
|
||
</p>
|
||
</div>
|
||
<div style="border: 1px solid #e0e0e0; padding: 1rem; border-radius: 0.5rem;">
|
||
<p><strong>Compare with PyTorch</strong></p>
|
||
<p style="margin: 0.5rem 0 0 0; font-size: 0.9rem; color: #666;">
|
||
Once your implementation works, compare with PyTorch’s equivalent.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<p>Take your time. The goal is not to finish fast. The goal is to understand deeply.</p>
|
||
<div style="background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); padding: 1.5rem 2rem; border-radius: 0.5rem; margin: 2rem 0; text-align: center;">
|
||
<p style="color: #f8fafc; font-size: 1.2rem; font-style: italic; margin: 0; font-weight: 500;">
|
||
“Building systems creates irreversible understanding.”
|
||
</p>
|
||
</div>
|
||
</section>
|
||
<section id="the-bigger-picture" class="level2">
|
||
<h2 class="anchored" data-anchor-id="the-bigger-picture">The Bigger Picture</h2>
|
||
<p>TinyTorch is one piece of a larger curriculum, and every piece exists for the same reason: students who only read do not internalize, and students who only code do not generalize. The <a href="https://mlsysbook.ai">Machine Learning Systems</a> textbook gives you the concepts: how training works, why accelerators matter, what makes inference cheap or expensive. TinyTorch makes you build the machinery yourself. The hardware kits put what you built on real devices, where memory limits, power budgets, and latency stop being abstractions. And StaffML tests whether you can reason about these systems under pressure, the way an interview or a production incident will.</p>
|
||
<p>This follows a long tradition in engineering education. You learned electronics by wiring a circuit on a breadboard. You learned architecture by laying out a processor on an FPGA. You learned operating systems by building a small kernel of your own, your first TinyOS. You do not understand a system until you have built one. The same tradition runs through systems education: SICP’s “build to understand” philosophy, xv6’s transparent operating system, Nachos, Pintos. TinyTorch brings it to machine learning, and it grew out of years of teaching these ideas at Harvard and building the open MLSysBook curriculum. The pedagogical principles are detailed in our <a href="https://arxiv.org/pdf/2601.19107">research paper</a>, which positions this work within decades of CS education research.</p>
|
||
<p>The next generation of engineers cannot rely on magic. They need to see how everything fits together, from a single tensor allocation up to a full training loop, and feel that the systems running modern AI are not an unreachable tower but something they can open, shape, and rebuild.</p>
|
||
<p>That is what TinyTorch offers: the confidence that comes from having built it yourself.</p>
|
||
</section>
|
||
<section id="for-instructors" class="level2">
|
||
<h2 class="anchored" data-anchor-id="for-instructors">For Instructors</h2>
|
||
<p>Every engineering course has a lab, because students learn to build by building. TinyTorch is that lab for machine learning systems, and it is built to be taught. The modules come with tests and autograding so you can guide students as they build, and the instructor hub at <a href="https://mlsysbook.ai">mlsysbook.ai</a> collects what you need to bring this into a classroom: the AI Engineering Blueprint, lecture slides, a course map, and assessment guides. These materials are still growing, and we welcome ideas and contributions from anyone teaching with them.</p>
|
||
</section>
|
||
<section id="make-it-better" class="level2">
|
||
<h2 class="anchored" data-anchor-id="make-it-better">Make It Better</h2>
|
||
<p>TinyTorch is open source, and it is built the way it teaches: in the open, by people who wanted to understand it. Every module, test, and milestone lives in the open, so if you find a bug, an explanation that did not land, or a cleaner way to teach a concept, you can fix it, and the next reader gets the benefit. The students who learn the most from TinyTorch are often the ones who end up improving it.</p>
|
||
<p>Found a problem? Built something better? Think a design choice is wrong? Bring it to <a href="https://mlsysbook.ai/git">mlsysbook.ai/git</a>.</p>
|
||
<p><em>Prof. Vijay Janapa Reddi</em><br> <em>(Harvard University)</em><br> <em>2025</em></p>
|
||
</section>
|
||
<section id="whats-next" class="level2">
|
||
<h2 class="anchored" data-anchor-id="whats-next">What’s Next?</h2>
|
||
<p><strong><a href="./big-picture.html">See the Big Picture →</a></strong>: how all 20 modules connect, what you will build, and which path to take.</p>
|
||
|
||
|
||
</section>
|
||
|
||
<a onclick="window.scrollTo(0, 0); return false;" role="button" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a></main> <!-- /main -->
|
||
<script id="quarto-html-after-body" type="application/javascript">
|
||
window.document.addEventListener("DOMContentLoaded", function (event) {
|
||
// Ensure there is a toggle, if there isn't float one in the top right
|
||
if (window.document.querySelector('.quarto-color-scheme-toggle') === null) {
|
||
const a = window.document.createElement('a');
|
||
a.classList.add('top-right');
|
||
a.classList.add('quarto-color-scheme-toggle');
|
||
a.href = "";
|
||
a.onclick = function() { try { window.quartoToggleColorScheme(); } catch {} return false; };
|
||
const i = window.document.createElement("i");
|
||
i.classList.add('bi');
|
||
a.appendChild(i);
|
||
window.document.body.appendChild(a);
|
||
}
|
||
setColorSchemeToggle(hasAlternateSentinel())
|
||
const icon = "";
|
||
const anchorJS = new window.AnchorJS();
|
||
anchorJS.options = {
|
||
placement: 'right',
|
||
icon: icon
|
||
};
|
||
anchorJS.add('.anchored');
|
||
const isCodeAnnotation = (el) => {
|
||
for (const clz of el.classList) {
|
||
if (clz.startsWith('code-annotation-')) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
const onCopySuccess = function(e) {
|
||
// button target
|
||
const button = e.trigger;
|
||
// don't keep focus
|
||
button.blur();
|
||
// flash "checked"
|
||
button.classList.add('code-copy-button-checked');
|
||
var currentTitle = button.getAttribute("title");
|
||
button.setAttribute("title", "Copied!");
|
||
let tooltip;
|
||
if (window.bootstrap) {
|
||
button.setAttribute("data-bs-toggle", "tooltip");
|
||
button.setAttribute("data-bs-placement", "left");
|
||
button.setAttribute("data-bs-title", "Copied!");
|
||
tooltip = new bootstrap.Tooltip(button,
|
||
{ trigger: "manual",
|
||
customClass: "code-copy-button-tooltip",
|
||
offset: [0, -8]});
|
||
tooltip.show();
|
||
}
|
||
setTimeout(function() {
|
||
if (tooltip) {
|
||
tooltip.hide();
|
||
button.removeAttribute("data-bs-title");
|
||
button.removeAttribute("data-bs-toggle");
|
||
button.removeAttribute("data-bs-placement");
|
||
}
|
||
button.setAttribute("title", currentTitle);
|
||
button.classList.remove('code-copy-button-checked');
|
||
}, 1000);
|
||
// clear code selection
|
||
e.clearSelection();
|
||
}
|
||
const getTextToCopy = function(trigger) {
|
||
const outerScaffold = trigger.parentElement.cloneNode(true);
|
||
const codeEl = outerScaffold.querySelector('code');
|
||
for (const childEl of codeEl.children) {
|
||
if (isCodeAnnotation(childEl)) {
|
||
childEl.remove();
|
||
}
|
||
}
|
||
return codeEl.innerText;
|
||
}
|
||
const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', {
|
||
text: getTextToCopy
|
||
});
|
||
clipboard.on('success', onCopySuccess);
|
||
if (window.document.getElementById('quarto-embedded-source-code-modal')) {
|
||
const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', {
|
||
text: getTextToCopy,
|
||
container: window.document.getElementById('quarto-embedded-source-code-modal')
|
||
});
|
||
clipboardModal.on('success', onCopySuccess);
|
||
}
|
||
var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//);
|
||
var mailtoRegex = new RegExp(/^mailto:/);
|
||
var filterRegex = new RegExp("https:\/\/mlsysbook\.ai\/tinytorch\/");
|
||
var isInternal = (href) => {
|
||
return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href);
|
||
}
|
||
// Inspect non-navigation links and adorn them if external
|
||
var links = window.document.querySelectorAll('a[href]:not(.nav-link):not(.navbar-brand):not(.toc-action):not(.sidebar-link):not(.sidebar-item-toggle):not(.pagination-link):not(.no-external):not([aria-hidden]):not(.dropdown-item):not(.quarto-navigation-tool):not(.about-link)');
|
||
for (var i=0; i<links.length; i++) {
|
||
const link = links[i];
|
||
if (!isInternal(link.href)) {
|
||
// undo the damage that might have been done by quarto-nav.js in the case of
|
||
// links that we want to consider external
|
||
if (link.dataset.originalHref !== undefined) {
|
||
link.href = link.dataset.originalHref;
|
||
}
|
||
// target, if specified
|
||
link.setAttribute("target", "_blank");
|
||
if (link.getAttribute("rel") === null) {
|
||
link.setAttribute("rel", "noopener");
|
||
}
|
||
}
|
||
}
|
||
function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) {
|
||
const config = {
|
||
allowHTML: true,
|
||
maxWidth: 500,
|
||
delay: 100,
|
||
arrow: false,
|
||
appendTo: function(el) {
|
||
return el.parentElement;
|
||
},
|
||
interactive: true,
|
||
interactiveBorder: 10,
|
||
theme: 'quarto',
|
||
placement: 'bottom-start',
|
||
};
|
||
if (contentFn) {
|
||
config.content = contentFn;
|
||
}
|
||
if (onTriggerFn) {
|
||
config.onTrigger = onTriggerFn;
|
||
}
|
||
if (onUntriggerFn) {
|
||
config.onUntrigger = onUntriggerFn;
|
||
}
|
||
window.tippy(el, config);
|
||
}
|
||
const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
|
||
for (var i=0; i<noterefs.length; i++) {
|
||
const ref = noterefs[i];
|
||
tippyHover(ref, function() {
|
||
// use id or data attribute instead here
|
||
let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
|
||
try { href = new URL(href).hash; } catch {}
|
||
const id = href.replace(/^#\/?/, "");
|
||
const note = window.document.getElementById(id);
|
||
if (note) {
|
||
return note.innerHTML;
|
||
} else {
|
||
return "";
|
||
}
|
||
});
|
||
}
|
||
const xrefs = window.document.querySelectorAll('a.quarto-xref');
|
||
const processXRef = (id, note) => {
|
||
// Strip column container classes
|
||
const stripColumnClz = (el) => {
|
||
el.classList.remove("page-full", "page-columns");
|
||
if (el.children) {
|
||
for (const child of el.children) {
|
||
stripColumnClz(child);
|
||
}
|
||
}
|
||
}
|
||
stripColumnClz(note)
|
||
if (id === null || id.startsWith('sec-')) {
|
||
// Special case sections, only their first couple elements
|
||
const container = document.createElement("div");
|
||
if (note.children && note.children.length > 2) {
|
||
container.appendChild(note.children[0].cloneNode(true));
|
||
for (let i = 1; i < note.children.length; i++) {
|
||
const child = note.children[i];
|
||
if (child.tagName === "P" && child.innerText === "") {
|
||
continue;
|
||
} else {
|
||
container.appendChild(child.cloneNode(true));
|
||
break;
|
||
}
|
||
}
|
||
if (window.Quarto?.typesetMath) {
|
||
window.Quarto.typesetMath(container);
|
||
}
|
||
return container.innerHTML
|
||
} else {
|
||
if (window.Quarto?.typesetMath) {
|
||
window.Quarto.typesetMath(note);
|
||
}
|
||
return note.innerHTML;
|
||
}
|
||
} else {
|
||
// Remove any anchor links if they are present
|
||
const anchorLink = note.querySelector('a.anchorjs-link');
|
||
if (anchorLink) {
|
||
anchorLink.remove();
|
||
}
|
||
if (window.Quarto?.typesetMath) {
|
||
window.Quarto.typesetMath(note);
|
||
}
|
||
if (note.classList.contains("callout")) {
|
||
return note.outerHTML;
|
||
} else {
|
||
return note.innerHTML;
|
||
}
|
||
}
|
||
}
|
||
for (var i=0; i<xrefs.length; i++) {
|
||
const xref = xrefs[i];
|
||
tippyHover(xref, undefined, function(instance) {
|
||
instance.disable();
|
||
let url = xref.getAttribute('href');
|
||
let hash = undefined;
|
||
if (url.startsWith('#')) {
|
||
hash = url;
|
||
} else {
|
||
try { hash = new URL(url).hash; } catch {}
|
||
}
|
||
if (hash) {
|
||
const id = hash.replace(/^#\/?/, "");
|
||
const note = window.document.getElementById(id);
|
||
if (note !== null) {
|
||
try {
|
||
const html = processXRef(id, note.cloneNode(true));
|
||
instance.setContent(html);
|
||
} finally {
|
||
instance.enable();
|
||
instance.show();
|
||
}
|
||
} else {
|
||
// See if we can fetch this
|
||
fetch(url.split('#')[0])
|
||
.then(res => res.text())
|
||
.then(html => {
|
||
const parser = new DOMParser();
|
||
const htmlDoc = parser.parseFromString(html, "text/html");
|
||
const note = htmlDoc.getElementById(id);
|
||
if (note !== null) {
|
||
const html = processXRef(id, note);
|
||
instance.setContent(html);
|
||
}
|
||
}).finally(() => {
|
||
instance.enable();
|
||
instance.show();
|
||
});
|
||
}
|
||
} else {
|
||
// See if we can fetch a full url (with no hash to target)
|
||
// This is a special case and we should probably do some content thinning / targeting
|
||
fetch(url)
|
||
.then(res => res.text())
|
||
.then(html => {
|
||
const parser = new DOMParser();
|
||
const htmlDoc = parser.parseFromString(html, "text/html");
|
||
const note = htmlDoc.querySelector('main.content');
|
||
if (note !== null) {
|
||
// This should only happen for chapter cross references
|
||
// (since there is no id in the URL)
|
||
// remove the first header
|
||
if (note.children.length > 0 && note.children[0].tagName === "HEADER") {
|
||
note.children[0].remove();
|
||
}
|
||
const html = processXRef(null, note);
|
||
instance.setContent(html);
|
||
}
|
||
}).finally(() => {
|
||
instance.enable();
|
||
instance.show();
|
||
});
|
||
}
|
||
}, function(instance) {
|
||
});
|
||
}
|
||
let selectedAnnoteEl;
|
||
const selectorForAnnotation = ( cell, annotation) => {
|
||
let cellAttr = 'data-code-cell="' + cell + '"';
|
||
let lineAttr = 'data-code-annotation="' + annotation + '"';
|
||
const selector = 'span[' + cellAttr + '][' + lineAttr + ']';
|
||
return selector;
|
||
}
|
||
const selectCodeLines = (annoteEl) => {
|
||
const doc = window.document;
|
||
const targetCell = annoteEl.getAttribute("data-target-cell");
|
||
const targetAnnotation = annoteEl.getAttribute("data-target-annotation");
|
||
const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation));
|
||
const lines = annoteSpan.getAttribute("data-code-lines").split(",");
|
||
const lineIds = lines.map((line) => {
|
||
return targetCell + "-" + line;
|
||
})
|
||
let top = null;
|
||
let height = null;
|
||
let parent = null;
|
||
if (lineIds.length > 0) {
|
||
//compute the position of the single el (top and bottom and make a div)
|
||
const el = window.document.getElementById(lineIds[0]);
|
||
top = el.offsetTop;
|
||
height = el.offsetHeight;
|
||
parent = el.parentElement.parentElement;
|
||
if (lineIds.length > 1) {
|
||
const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]);
|
||
const bottom = lastEl.offsetTop + lastEl.offsetHeight;
|
||
height = bottom - top;
|
||
}
|
||
if (top !== null && height !== null && parent !== null) {
|
||
// cook up a div (if necessary) and position it
|
||
let div = window.document.getElementById("code-annotation-line-highlight");
|
||
if (div === null) {
|
||
div = window.document.createElement("div");
|
||
div.setAttribute("id", "code-annotation-line-highlight");
|
||
div.style.position = 'absolute';
|
||
parent.appendChild(div);
|
||
}
|
||
div.style.top = top - 2 + "px";
|
||
div.style.height = height + 4 + "px";
|
||
div.style.left = 0;
|
||
let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter");
|
||
if (gutterDiv === null) {
|
||
gutterDiv = window.document.createElement("div");
|
||
gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter");
|
||
gutterDiv.style.position = 'absolute';
|
||
const codeCell = window.document.getElementById(targetCell);
|
||
const gutter = codeCell.querySelector('.code-annotation-gutter');
|
||
gutter.appendChild(gutterDiv);
|
||
}
|
||
gutterDiv.style.top = top - 2 + "px";
|
||
gutterDiv.style.height = height + 4 + "px";
|
||
}
|
||
selectedAnnoteEl = annoteEl;
|
||
}
|
||
};
|
||
const unselectCodeLines = () => {
|
||
const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"];
|
||
elementsIds.forEach((elId) => {
|
||
const div = window.document.getElementById(elId);
|
||
if (div) {
|
||
div.remove();
|
||
}
|
||
});
|
||
selectedAnnoteEl = undefined;
|
||
};
|
||
// Handle positioning of the toggle
|
||
window.addEventListener(
|
||
"resize",
|
||
throttle(() => {
|
||
elRect = undefined;
|
||
if (selectedAnnoteEl) {
|
||
selectCodeLines(selectedAnnoteEl);
|
||
}
|
||
}, 10)
|
||
);
|
||
function throttle(fn, ms) {
|
||
let throttle = false;
|
||
let timer;
|
||
return (...args) => {
|
||
if(!throttle) { // first call gets through
|
||
fn.apply(this, args);
|
||
throttle = true;
|
||
} else { // all the others get throttled
|
||
if(timer) clearTimeout(timer); // cancel #2
|
||
timer = setTimeout(() => {
|
||
fn.apply(this, args);
|
||
timer = throttle = false;
|
||
}, ms);
|
||
}
|
||
};
|
||
}
|
||
// Attach click handler to the DT
|
||
const annoteDls = window.document.querySelectorAll('dt[data-target-cell]');
|
||
for (const annoteDlNode of annoteDls) {
|
||
annoteDlNode.addEventListener('click', (event) => {
|
||
const clickedEl = event.target;
|
||
if (clickedEl !== selectedAnnoteEl) {
|
||
unselectCodeLines();
|
||
const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active');
|
||
if (activeEl) {
|
||
activeEl.classList.remove('code-annotation-active');
|
||
}
|
||
selectCodeLines(clickedEl);
|
||
clickedEl.classList.add('code-annotation-active');
|
||
} else {
|
||
// Unselect the line
|
||
unselectCodeLines();
|
||
clickedEl.classList.remove('code-annotation-active');
|
||
}
|
||
});
|
||
}
|
||
const findCites = (el) => {
|
||
const parentEl = el.parentElement;
|
||
if (parentEl) {
|
||
const cites = parentEl.dataset.cites;
|
||
if (cites) {
|
||
return {
|
||
el,
|
||
cites: cites.split(' ')
|
||
};
|
||
} else {
|
||
return findCites(el.parentElement)
|
||
}
|
||
} else {
|
||
return undefined;
|
||
}
|
||
};
|
||
var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
|
||
for (var i=0; i<bibliorefs.length; i++) {
|
||
const ref = bibliorefs[i];
|
||
const citeInfo = findCites(ref);
|
||
if (citeInfo) {
|
||
tippyHover(citeInfo.el, function() {
|
||
var popup = window.document.createElement('div');
|
||
citeInfo.cites.forEach(function(cite) {
|
||
var citeDiv = window.document.createElement('div');
|
||
citeDiv.classList.add('hanging-indent');
|
||
citeDiv.classList.add('csl-entry');
|
||
var biblioDiv = window.document.getElementById('ref-' + cite);
|
||
if (biblioDiv) {
|
||
citeDiv.innerHTML = biblioDiv.innerHTML;
|
||
}
|
||
popup.appendChild(citeDiv);
|
||
});
|
||
return popup.innerHTML;
|
||
});
|
||
}
|
||
}
|
||
});
|
||
</script>
|
||
<nav class="page-navigation">
|
||
<div class="nav-page nav-page-previous">
|
||
</div>
|
||
<div class="nav-page nav-page-next">
|
||
<a href="./big-picture.html" class="pagination-link" aria-label="Big Picture">
|
||
<span class="nav-page-text">Big Picture</span> <i class="bi bi-arrow-right-short"></i>
|
||
</a>
|
||
</div>
|
||
</nav>
|
||
</div> <!-- /content -->
|
||
<footer class="footer">
|
||
<div class="nav-footer">
|
||
<div class="nav-footer-left">
|
||
<p>© 2024-2026 Harvard University. Licensed under <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC-BY-NC-SA 4.0</a></p>
|
||
</div>
|
||
<div class="nav-footer-center">
|
||
<p>Part of the <a href="https://mlsysbook.ai">Machine Learning Systems</a> textbook</p>
|
||
</div>
|
||
<div class="nav-footer-right">
|
||
<ul class="footer-items list-unstyled">
|
||
<li class="nav-item compact">
|
||
<a class="nav-link" href="https://github.com/harvard-edge/cs249r_book">
|
||
<i class="bi bi-github" role="img" aria-label="View source on GitHub">
|
||
</i>
|
||
</a>
|
||
</li>
|
||
<li class="nav-item compact">
|
||
<a class="nav-link" href="https://github.com/harvard-edge/cs249r_book">
|
||
<i class="bi bi-star" role="img" aria-label="Star this repository">
|
||
</i>
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
<script>
|
||
/**
|
||
* Subscribe Modal Component for TinyTorch (Quarto version)
|
||
* Elegant popup subscription form
|
||
*/
|
||
|
||
(function() {
|
||
'use strict';
|
||
|
||
function createModalHTML() {
|
||
return `
|
||
<div id="subscribe-modal" class="modal-overlay" style="display: none;">
|
||
<div class="modal-container">
|
||
<button class="modal-close" data-close-modal aria-label="Close">×</button>
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<div class="modal-brand-row">
|
||
<span class="modal-brand-item">📚 MLSysBook</span>
|
||
</div>
|
||
<h2 class="modal-title">Stay in the Loop</h2>
|
||
<p class="modal-subtitle">Get updates on new chapters, hands-on labs, and ML systems resources.</p>
|
||
</div>
|
||
<form id="subscribe-modal-form" class="subscribe-form" action="https://buttondown.email/api/emails/embed-subscribe/mlsysbook" method="post">
|
||
<div class="form-row">
|
||
<div class="form-group">
|
||
<label for="modal-first-name">First name</label>
|
||
<input type="text" id="modal-first-name" name="metadata__first_name" required placeholder="Jane">
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="modal-last-name">Last name</label>
|
||
<input type="text" id="modal-last-name" name="metadata__last_name" required placeholder="Smith">
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="modal-email">Email</label>
|
||
<input type="email" id="modal-email" name="email" required placeholder="jane@university.edu">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>I am a...</label>
|
||
<div class="role-options role-options-three-compact">
|
||
<label class="role-option">
|
||
<input type="radio" name="metadata__role" value="educator" required>
|
||
<span class="role-label">👨🏫 Educator</span>
|
||
</label>
|
||
<label class="role-option">
|
||
<input type="radio" name="metadata__role" value="student">
|
||
<span class="role-label">🎓 Student</span>
|
||
</label>
|
||
<label class="role-option">
|
||
<input type="radio" name="metadata__role" value="industry">
|
||
<span class="role-label">💼 Industry</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="modal-organization">Organization <span class="optional-label">(optional)</span></label>
|
||
<input type="text" id="modal-organization" name="metadata__organization" placeholder="University or company">
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="modal-motivation">What brings you here? <span class="optional-label">(optional)</span></label>
|
||
<textarea id="modal-motivation" name="metadata__motivation" rows="2" placeholder="e.g., teaching a course, learning ML systems, building edge devices..."></textarea>
|
||
</div>
|
||
<input type="hidden" name="tag" value="tinytorch-site">
|
||
<button type="submit" class="btn btn-primary subscribe-btn">Subscribe</button>
|
||
<p class="form-note">No spam, ever. Unsubscribe anytime.</p>
|
||
</form>
|
||
<div id="modal-subscribe-success" class="subscribe-success" style="display: none;">
|
||
<div class="success-icon">🎉</div>
|
||
<h3>You're in!</h3>
|
||
<p>Welcome to the ML systems community. We'll keep you updated on new content.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
function createModalCSS() {
|
||
const style = document.createElement('style');
|
||
style.textContent = `
|
||
.modal-overlay {
|
||
position: fixed; top: 0; left: 0; right: 0; bottom: 0;
|
||
background: rgba(15, 23, 42, 0.6); backdrop-filter: blur(4px);
|
||
z-index: 10001; align-items: center; justify-content: center;
|
||
padding: 1rem; animation: fadeIn 0.2s ease;
|
||
}
|
||
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||
@keyframes slideUp { from { opacity: 0; transform: translateY(20px) scale(0.98); } to { opacity: 1; transform: translateY(0) scale(1); } }
|
||
.modal-container {
|
||
background: white; border-radius: 16px; max-width: 440px; width: 100%;
|
||
max-height: 90vh; overflow-y: auto; position: relative;
|
||
box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
||
animation: slideUp 0.3s ease; margin: auto;
|
||
}
|
||
.modal-close {
|
||
position: absolute; top: 1rem; right: 1rem; width: 36px; height: 36px;
|
||
border: none; background: #f8fafc; border-radius: 50%; font-size: 1.5rem;
|
||
color: #64748b; cursor: pointer; display: flex; align-items: center;
|
||
justify-content: center; transition: all 0.2s ease; z-index: 10; line-height: 1;
|
||
}
|
||
.modal-close:hover { background: white; color: #0f172a; transform: scale(1.05); }
|
||
.modal-content { padding: 2rem 2.5rem 2.5rem 2.5rem; }
|
||
.modal-header { text-align: center; margin-bottom: 1.5rem; display: flex; flex-direction: column; align-items: center; }
|
||
.modal-brand-row { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; margin-bottom: 1rem; }
|
||
.modal-brand-item { font-size: 0.8rem; font-weight: 600; color: #374151; background: #f3f4f6; padding: 0.3rem 0.6rem; border-radius: 5px; }
|
||
.modal-title { font-size: 1.5rem; font-weight: 700; color: #0f172a; margin: 0 0 0.4rem 0; line-height: 1.2; width: 100%; }
|
||
.modal-subtitle { font-size: 0.9rem; color: #64748b; margin: 0; line-height: 1.5; max-width: 320px; }
|
||
.subscribe-form { display: flex; flex-direction: column; gap: 1.25rem; }
|
||
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
|
||
.form-row .form-group { min-width: 0; }
|
||
.form-row .form-group input { width: 100%; box-sizing: border-box; }
|
||
.form-group { display: flex; flex-direction: column; gap: 0.5rem; }
|
||
.form-group label { font-size: 0.9rem; font-weight: 600; color: #0f172a; }
|
||
.optional-label { font-weight: 400; color: #64748b; }
|
||
.form-group input[type="text"], .form-group input[type="email"], .form-group textarea {
|
||
padding: 0.875rem 1rem; border: 1px solid #cbd5e1; border-radius: 8px;
|
||
font-size: 1rem; transition: all 0.2s ease; background: #f8fafc; font-family: inherit;
|
||
}
|
||
.form-group textarea { resize: vertical; min-height: 60px; }
|
||
.form-group input:focus, .form-group textarea:focus {
|
||
outline: none; border-color: #3b82f6; background: white;
|
||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
||
}
|
||
.form-group input::placeholder, .form-group textarea::placeholder { color: #94a3b8; }
|
||
.role-options { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
|
||
.role-options-three-compact { grid-template-columns: repeat(3, 1fr); }
|
||
.role-option { cursor: pointer; }
|
||
.role-option input[type="radio"] { position: absolute; opacity: 0; width: 0; height: 0; }
|
||
.role-label {
|
||
display: flex; align-items: center; justify-content: center; gap: 0.5rem;
|
||
padding: 0.75rem 1rem; border: 2px solid #e2e8f0; border-radius: 8px;
|
||
font-size: 0.9rem; font-weight: 500; color: #475569; transition: all 0.2s ease; background: #f8fafc;
|
||
}
|
||
.role-options-three-compact .role-label { padding: 0.625rem 0.5rem; font-size: 0.8rem; text-align: center; }
|
||
.role-option input[type="radio"]:checked + .role-label { border-color: #3b82f6; background: rgba(59, 130, 246, 0.08); color: #3b82f6; }
|
||
.role-option:hover .role-label { border-color: #cbd5e1; background: white; }
|
||
.subscribe-btn { width: 100%; padding: 1rem; font-size: 1rem; margin-top: 0.5rem;
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
border-radius: 8px; text-decoration: none; font-weight: 600; border: none; cursor: pointer;
|
||
background: linear-gradient(135deg, #f97316 0%, #ea580c 100%); color: white; font-family: inherit;
|
||
}
|
||
.subscribe-btn:hover { background: linear-gradient(135deg, #fb923c 0%, #f97316 100%); transform: translateY(-1px); box-shadow: 0 4px 12px rgba(249, 115, 22, 0.3); }
|
||
.form-note { text-align: center; font-size: 0.85rem; color: #64748b; margin: 0; }
|
||
.subscribe-success { text-align: center; padding: 2rem 1rem; }
|
||
.success-icon { font-size: 3rem; margin-bottom: 1rem; }
|
||
.subscribe-success h3 { font-size: 1.5rem; font-weight: 600; color: #0f172a; margin-bottom: 0.5rem; }
|
||
.subscribe-success p { color: #475569; font-size: 1rem; }
|
||
|
||
/* Quarto dark mode */
|
||
.quarto-dark .modal-container, html[data-bs-theme="dark"] .modal-container { background: #1e293b; }
|
||
.quarto-dark .modal-close, html[data-bs-theme="dark"] .modal-close { background: #0f172a; color: #94a3b8; }
|
||
.quarto-dark .modal-title, html[data-bs-theme="dark"] .modal-title,
|
||
.quarto-dark .form-group label, html[data-bs-theme="dark"] .form-group label { color: #f1f5f9; }
|
||
.quarto-dark .modal-subtitle, html[data-bs-theme="dark"] .modal-subtitle { color: #cbd5e1; }
|
||
.quarto-dark .form-group input, html[data-bs-theme="dark"] .form-group input,
|
||
.quarto-dark .form-group textarea, html[data-bs-theme="dark"] .form-group textarea { background: #0f172a; border-color: #334155; color: #f1f5f9; }
|
||
.quarto-dark .role-label, html[data-bs-theme="dark"] .role-label { background: #0f172a; border-color: #334155; color: #cbd5e1; }
|
||
|
||
@media (max-width: 640px) { .modal-content { padding: 2rem 1.5rem; } .form-row { grid-template-columns: 1fr; } }
|
||
`;
|
||
return style;
|
||
}
|
||
|
||
function initModal() {
|
||
document.head.appendChild(createModalCSS());
|
||
const modalDiv = document.createElement('div');
|
||
modalDiv.innerHTML = createModalHTML();
|
||
document.body.appendChild(modalDiv.firstElementChild);
|
||
|
||
const modal = document.getElementById('subscribe-modal');
|
||
const form = document.getElementById('subscribe-modal-form');
|
||
const success = document.getElementById('modal-subscribe-success');
|
||
|
||
window.openSubscribeModal = function() {
|
||
modal.style.display = 'flex';
|
||
document.body.style.overflow = 'hidden';
|
||
setTimeout(() => { const fi = document.getElementById('modal-first-name'); if (fi) fi.focus(); }, 100);
|
||
};
|
||
|
||
window.closeSubscribeModal = function() {
|
||
modal.style.display = 'none';
|
||
document.body.style.overflow = '';
|
||
setTimeout(() => { form.style.display = 'flex'; form.reset(); success.style.display = 'none'; }, 300);
|
||
};
|
||
|
||
modal.addEventListener('click', (e) => { if (e.target === modal) closeSubscribeModal(); });
|
||
const closeBtn = modal.querySelector('[data-close-modal]');
|
||
if (closeBtn) closeBtn.addEventListener('click', closeSubscribeModal);
|
||
document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && modal.style.display === 'flex') closeSubscribeModal(); });
|
||
|
||
form.addEventListener('submit', function() {
|
||
setTimeout(() => { form.style.display = 'none'; success.style.display = 'block'; setTimeout(closeSubscribeModal, 5000); }, 100);
|
||
});
|
||
|
||
if (window.location.hash === '#subscribe') setTimeout(() => openSubscribeModal(), 300);
|
||
window.addEventListener('hashchange', function() { if (window.location.hash === '#subscribe') openSubscribeModal(); });
|
||
|
||
setTimeout(() => {
|
||
document.querySelectorAll('#navbar-subscribe-btn, a[href*="#subscribe"], a.subscribe-link').forEach(link => {
|
||
link.addEventListener('click', function(e) { e.preventDefault(); openSubscribeModal(); });
|
||
});
|
||
}, 1000);
|
||
}
|
||
|
||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', initModal);
|
||
else initModal();
|
||
})();
|
||
</script>
|
||
<script>
|
||
/**
|
||
* Interactive ML History Timeline (Quarto version)
|
||
* Handles popup functionality for milestone cards
|
||
*/
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
const timelineData = {
|
||
perceptron: {
|
||
year: "1958", title: "The Perceptron", researcher: "Frank Rosenblatt",
|
||
subtitle: "The first neural network architecture starts the field",
|
||
achievement: "Binary classification with a forward pass",
|
||
architecture: "Input → Linear → Sigmoid → Output",
|
||
whatYouBuild: ["Binary classification with random weights", "Simple but revolutionary architecture", "YOUR Linear layer recreates history"],
|
||
systemsInsights: ["Memory: O(n) parameters", "Compute: O(n) operations", "Limitation: Only linearly separable problems"],
|
||
modules: "After Modules 01-03", expectedResults: "~50% with untrained random weights",
|
||
commands: ["tito milestone run perceptron"]
|
||
},
|
||
xor: {
|
||
year: "1969", title: "The XOR Crisis", researcher: "Minsky & Papert",
|
||
subtitle: "Hidden layers solve non-linear problems that nearly ended AI research",
|
||
achievement: "Non-linear learning through hidden representations",
|
||
architecture: "Input → Linear → ReLU → Linear → Output",
|
||
whatYouBuild: ["Hidden layers enable non-linear solutions", "Multi-layer networks break through limitations", "YOUR autograd makes it possible"],
|
||
systemsInsights: ["Memory: O(n²) with hidden layers", "Compute: O(n²) operations", "Breakthrough: Hidden representations"],
|
||
modules: "After Modules 02-06", expectedResults: "50% (single layer) → 100% (multi-layer) on XOR",
|
||
commands: ["tito milestone run xor"]
|
||
},
|
||
mlp: {
|
||
year: "1986", title: "MLP Revival", researcher: "Backpropagation Era",
|
||
subtitle: "Backpropagation enables training deep networks on real datasets",
|
||
achievement: "Multi-class digit recognition",
|
||
architecture: "Images → Flatten → Linear → ReLU → Linear → ReLU → Linear → Classes",
|
||
whatYouBuild: ["XOR solved with hidden layers", "TinyDigits classification", "YOUR training pipeline learns real images"],
|
||
systemsInsights: ["Memory: ~2.4K parameters for TinyDigits", "Compute: Dense matrix operations", "Architecture: Multi-layer feature learning"],
|
||
modules: "After Modules 01-08", expectedResults: "Solves XOR, 85%+ on TinyDigits",
|
||
commands: ["tito milestone run mlp"]
|
||
},
|
||
cnn: {
|
||
year: "1998", title: "CNN Revolution", researcher: "Yann LeCun",
|
||
subtitle: "CNNs exploit spatial structure for computer vision—enabling modern AI",
|
||
achievement: "Spatial intelligence for computer vision",
|
||
architecture: "Images → Conv → ReLU → Pool → Conv → ReLU → Pool → Flatten → Linear → Classes",
|
||
whatYouBuild: ["Convolutional feature extraction", "Natural image classification (CIFAR-10)", "YOUR Conv2d + MaxPool2d unlock spatial intelligence"],
|
||
systemsInsights: ["Memory: ~1M parameters (weight sharing reduces vs dense)", "Compute: Convolution is intensive but parallelizable", "Architecture: Local connectivity + translation invariance"],
|
||
modules: "After Modules 02-09", expectedResults: "75%+ accuracy on CIFAR-10 ✨",
|
||
commands: ["tito milestone run cnn"], northStar: true
|
||
},
|
||
transformer: {
|
||
year: "2017", title: "Transformer Era", researcher: "Vaswani et al.",
|
||
subtitle: "Attention mechanism launches the LLM revolution (GPT, BERT, ChatGPT)",
|
||
achievement: "Self-attention for language understanding",
|
||
architecture: "Tokens → Embeddings → Attention → FFN → ... → Attention → Output",
|
||
whatYouBuild: ["Self-attention mechanisms", "Autoregressive text generation", "YOUR attention implementation generates language"],
|
||
systemsInsights: ["Memory: O(n²) attention requires careful management", "Compute: Highly parallelizable", "Architecture: Long-range dependencies"],
|
||
modules: "After Modules 02-13", expectedResults: "Loss < 1.5, coherent responses to questions",
|
||
commands: ["tito milestone run transformer"]
|
||
},
|
||
olympics: {
|
||
year: "2018", title: "MLPerf Torch Olympics", researcher: "MLCommons (founded 2018)",
|
||
subtitle: "Systematic optimization becomes essential as models grow larger",
|
||
achievement: "Production-ready optimization",
|
||
architecture: "Profile → Compress → Accelerate",
|
||
whatYouBuild: ["Performance profiling and bottleneck analysis", "Model compression (quantization + pruning)", "Inference acceleration (KV-cache + batching)"],
|
||
systemsInsights: ["Memory: 4-16× compression through quantization/pruning", "Speed: 12-40× faster generation with KV-cache + batching", "Workflow: Systematic 'measure → optimize → validate' methodology"],
|
||
modules: "After Modules 14-18", expectedResults: "8-16× smaller models, 12-40× faster inference",
|
||
commands: ["tito milestone run mlperf"]
|
||
}
|
||
};
|
||
|
||
// Create popup element
|
||
let popup = document.getElementById('ml-timeline-popup');
|
||
if (!popup) {
|
||
popup = document.createElement('div');
|
||
popup.id = 'ml-timeline-popup';
|
||
popup.className = 'ml-timeline-popup-overlay';
|
||
popup.innerHTML = '<div class="ml-timeline-popup"></div>';
|
||
document.body.appendChild(popup);
|
||
}
|
||
|
||
// Handle clicks on timeline items
|
||
document.querySelectorAll('.ml-timeline-content').forEach(card => {
|
||
card.style.cursor = 'pointer';
|
||
card.addEventListener('click', function() {
|
||
const item = this.closest('.ml-timeline-item');
|
||
// Get milestone type from class list (second class after 'ml-timeline-item' and 'left'/'right')
|
||
const classes = Array.from(item.classList);
|
||
const milestoneType = classes.find(c => !['ml-timeline-item', 'left', 'right'].includes(c));
|
||
const data = timelineData[milestoneType];
|
||
if (!data) return;
|
||
|
||
const popupInner = popup.querySelector('.ml-timeline-popup');
|
||
popupInner.innerHTML = `
|
||
<button class="ml-timeline-popup-close" aria-label="Close">×</button>
|
||
<h3><span style="color: #f97316; font-size: 0.85rem; display: block; margin-bottom: 0.25rem;">${data.year}</span>${data.title}</h3>
|
||
<p style="color: #64748b; margin: 0.5rem 0 1rem 0;">${data.subtitle}</p>
|
||
${data.northStar ? '<div style="background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); padding: 1rem; border-radius: 0.5rem; margin: 1rem 0; border-left: 4px solid #f59e0b;"><strong>🎯 North Star Achievement</strong> — This is a major milestone in your TinyTorch journey!</div>' : ''}
|
||
<div style="margin: 1rem 0;"><h4 style="font-size: 0.95rem; margin: 0 0 0.5rem 0;">The ${data.researcher} Breakthrough</h4><p><strong>${data.achievement}</strong></p></div>
|
||
<div style="margin: 1rem 0;"><h4 style="font-size: 0.95rem; margin: 0 0 0.5rem 0;">Architecture</h4><div style="background: #f8fafc; padding: 0.75rem; border-radius: 0.375rem; font-family: monospace; font-size: 0.85rem;">${data.architecture}</div></div>
|
||
<div style="margin: 1rem 0;"><h4 style="font-size: 0.95rem; margin: 0 0 0.5rem 0;">What You'll Build</h4><ul>${data.whatYouBuild.map(i => `<li>${i}</li>`).join('')}</ul></div>
|
||
<div style="margin: 1rem 0;"><h4 style="font-size: 0.95rem; margin: 0 0 0.5rem 0;">Systems Insights</h4><ul>${data.systemsInsights.map(i => `<li>${i}</li>`).join('')}</ul></div>
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin: 1rem 0;">
|
||
<div style="background: #f8fafc; padding: 0.75rem; border-radius: 0.375rem;"><div style="font-size: 0.75rem; color: #64748b; margin-bottom: 0.25rem;">Prerequisites</div><div style="font-weight: 600;">${data.modules}</div></div>
|
||
<div style="background: #f8fafc; padding: 0.75rem; border-radius: 0.375rem;"><div style="font-size: 0.75rem; color: #64748b; margin-bottom: 0.25rem;">Expected Results</div><div style="font-weight: 600;">${data.expectedResults}</div></div>
|
||
</div>
|
||
<div style="margin: 1rem 0;"><h4 style="font-size: 0.95rem; margin: 0 0 0.5rem 0;">Try It Yourself</h4><div style="background: #f8fafc; padding: 0.75rem; border-radius: 0.375rem; font-family: monospace; font-size: 0.85rem;">${data.commands.join('\n')}</div></div>
|
||
`;
|
||
|
||
popup.classList.add('active');
|
||
popup.style.display = 'flex';
|
||
|
||
popup.querySelector('.ml-timeline-popup-close').addEventListener('click', () => {
|
||
popup.classList.remove('active');
|
||
popup.style.display = 'none';
|
||
});
|
||
});
|
||
});
|
||
|
||
// Close on background click
|
||
popup.addEventListener('click', function(e) { if (e.target === popup) { popup.classList.remove('active'); popup.style.display = 'none'; } });
|
||
// Close on ESC
|
||
document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && popup.classList.contains('active')) { popup.classList.remove('active'); popup.style.display = 'none'; } });
|
||
});
|
||
</script>
|
||
<script>
|
||
// Inject subtitle + framework version chip under sidebar logo.
|
||
// The chip's version literal is sourced from tinytorch/settings.ini and
|
||
// kept in sync by the tinytorch-publish-live workflow's UPDATE_VERSION
|
||
// step on each release. Update marker for sed: TINYTORCH_VERSION_CHIP.
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
const sidebarLogo = document.querySelector('.sidebar-logo');
|
||
if (!sidebarLogo) return;
|
||
|
||
// The logo <img> sits inside Quarto's <a class="sidebar-logo-link"> wrapper.
|
||
// Inserting our subtitle as a sibling of the <img> would nest the subtitle's
|
||
// link INSIDE that anchor — invalid HTML, so the browser fires the outer logo
|
||
// link (./index.html) instead of navigating to the textbook. Insert AFTER the
|
||
// logo anchor, as a child of .sidebar-header, so our links are not nested.
|
||
const logoLink = sidebarLogo.closest('.sidebar-logo-link') || sidebarLogo;
|
||
const anchorHost = logoLink.parentElement;
|
||
|
||
// 1. Existing subtitle — what TinyTorch IS in relation to the textbook.
|
||
const subtitle = document.createElement('div');
|
||
subtitle.className = 'sidebar-subtitle';
|
||
subtitle.innerHTML = 'A Build-It-Yourself Companion to the<br><a href="https://mlsysbook.ai" style="color: #D4740C; text-decoration: none;">Machine Learning Systems</a> textbook';
|
||
anchorHost.insertBefore(subtitle, logoLink.nextSibling);
|
||
|
||
// 2. Framework version chip — explicitly identifies TinyTorch's version,
|
||
// not the textbook's. Visually separated so the reader does not parse
|
||
// the version as part of the subtitle prose. Click → GitHub Releases
|
||
// filtered for tinytorch tags (the canonical changelog destination).
|
||
const chipWrap = document.createElement('div');
|
||
chipWrap.className = 'tinytorch-version-chip-wrap';
|
||
|
||
const chip = document.createElement('a');
|
||
chip.className = 'tinytorch-version-chip';
|
||
chip.href = 'https://github.com/harvard-edge/cs249r_book/releases?q=tinytorch';
|
||
chip.target = '_blank';
|
||
chip.rel = 'noopener';
|
||
chip.innerHTML = '🔥 TinyTorch v0.1.13 →'; // TINYTORCH_VERSION_CHIP
|
||
|
||
chipWrap.appendChild(chip);
|
||
subtitle.parentNode.insertBefore(chipWrap, subtitle.nextSibling);
|
||
});
|
||
</script>
|
||
<style>
|
||
.sidebar-subtitle {
|
||
text-align: center;
|
||
font-size: 0.8rem;
|
||
color: #6b7280;
|
||
line-height: 1.4;
|
||
padding: 0 1rem 0.5rem 1rem;
|
||
margin-top: 0.5rem;
|
||
}
|
||
.sidebar-subtitle a:hover {
|
||
color: #f97316 !important;
|
||
}
|
||
|
||
/* Version chip — divider above + amber pill anchored to TinyTorch brand */
|
||
.tinytorch-version-chip-wrap {
|
||
text-align: center;
|
||
margin: 0 1rem;
|
||
padding: 0.5rem 0 0.75rem;
|
||
border-top: 1px solid #e5e7eb;
|
||
}
|
||
.tinytorch-version-chip {
|
||
display: inline-block;
|
||
padding: 0.15rem 0.65rem;
|
||
border: 1px solid #D4740C;
|
||
border-radius: 999px;
|
||
background: rgba(212, 116, 12, 0.08);
|
||
color: #D4740C !important; /* override Quarto's default link color */
|
||
font-size: 0.72rem;
|
||
font-weight: 600;
|
||
text-decoration: none !important;
|
||
white-space: nowrap;
|
||
letter-spacing: 0.01em;
|
||
transition: background-color 0.15s ease;
|
||
}
|
||
.tinytorch-version-chip:hover {
|
||
background: rgba(212, 116, 12, 0.18);
|
||
color: #D4740C !important;
|
||
text-decoration: none;
|
||
}
|
||
|
||
/* Dark-mode overrides — brighter amber to match dark-mode.scss $accent */
|
||
[data-bs-theme="dark"] .tinytorch-version-chip-wrap {
|
||
border-top-color: #454d55;
|
||
}
|
||
[data-bs-theme="dark"] .tinytorch-version-chip {
|
||
border-color: #F59E0B;
|
||
color: #F59E0B !important;
|
||
background: rgba(245, 158, 11, 0.1);
|
||
}
|
||
[data-bs-theme="dark"] .tinytorch-version-chip:hover {
|
||
background: rgba(245, 158, 11, 0.2);
|
||
color: #F59E0B !important;
|
||
}
|
||
</style>
|
||
<!--
|
||
MLSysBook release-pill — shared footer version chip for Quarto + static sites.
|
||
|
||
Renders a small "v0.1.0 · Apr 26, 2026" chip from a deployed
|
||
release-manifest.json. Best-effort chrome: silent on any fetch failure
|
||
(manifest missing, offline, CORS). Use at any site that emits a manifest
|
||
via scripts/version/release.py emit-manifest.
|
||
|
||
── Standardized placement (all MLSysBook sites) ──
|
||
|
||
The chip lives in the page-footer, right slot, so it reads as an
|
||
intentional part of the footer bar (not dangling below the page). Two
|
||
pieces per site:
|
||
|
||
1. This file loads the style + populator script site-wide:
|
||
|
||
format:
|
||
html:
|
||
include-in-header:
|
||
- text: |
|
||
<meta name="release-manifest" content="/<project-base>/release-manifest.json">
|
||
include-after-body:
|
||
- file: ../shared/release/release-pill.html
|
||
|
||
2. Each page-footer places the chip span where it should render:
|
||
|
||
website:
|
||
page-footer:
|
||
right:
|
||
- text: |
|
||
<span class="release-pill" data-release-pill></span>
|
||
- icon: github
|
||
href: ...
|
||
|
||
The meta tag tells the script where to find the manifest. The script
|
||
populates every span carrying data-release-pill, so the chip can sit in
|
||
the footer (canonical), an about page, or anywhere else.
|
||
|
||
── Manifest contract ──
|
||
|
||
The manifest is the JSON written by scripts/version/release.py
|
||
emit-manifest. Required keys: releaseId, releaseHash. Optional but
|
||
recommended: buildDate, project. Anything else is ignored.
|
||
|
||
── Why runtime fetch instead of build-time templating ──
|
||
|
||
Build-time templating would be deterministic but requires per-project
|
||
Lua/template machinery. Runtime fetch is project-agnostic and works
|
||
identically across Quarto, Next.js, and plain HTML. The one fetch per
|
||
page-load is cheap and the chip degrades to nothing on failure.
|
||
-->
|
||
|
||
<style>
|
||
/* Fixed muted gray on every site — the chip must look identical regardless of
|
||
each Quarto theme's accent colors (do NOT inherit --bs-secondary / link color). */
|
||
.release-pill {
|
||
display: inline-flex;
|
||
align-items: baseline;
|
||
gap: 0.25em;
|
||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
|
||
font-size: 0.75rem;
|
||
line-height: 1;
|
||
color: var(--release-pill-color, #6c757d);
|
||
}
|
||
.release-pill a,
|
||
.release-pill a:visited,
|
||
.release-pill-version,
|
||
.release-pill-date {
|
||
color: var(--release-pill-color, #6c757d);
|
||
text-decoration: none;
|
||
}
|
||
.release-pill a:hover {
|
||
text-decoration: underline;
|
||
text-underline-offset: 2px;
|
||
}
|
||
.release-pill-date {
|
||
opacity: 0.75;
|
||
}
|
||
</style>
|
||
|
||
<script>
|
||
(function () {
|
||
var pills = document.querySelectorAll('[data-release-pill]');
|
||
if (!pills.length) return;
|
||
|
||
// Manifest URL resolution order:
|
||
// 1. data-manifest attribute on the pill (per-page override)
|
||
// 2. <meta name="release-manifest" content="..."> in <head>
|
||
// 3. './release-manifest.json' relative to current page (fallback)
|
||
var meta = document.querySelector('meta[name="release-manifest"]');
|
||
var metaPath = meta && meta.getAttribute('content');
|
||
|
||
fetch(metaPath || './release-manifest.json', { cache: 'no-store' })
|
||
.then(function (res) { return res.ok ? res.json() : null; })
|
||
.then(function (m) {
|
||
if (!m || !m.releaseId || !m.releaseHash) return;
|
||
var date = m.buildDate
|
||
? new Date(m.buildDate).toLocaleDateString('en-US',
|
||
{ year: 'numeric', month: 'short', day: 'numeric' })
|
||
: '';
|
||
var shortHash = String(m.releaseHash).slice(0, 7);
|
||
var title =
|
||
(m.project ? m.project + ' ' : '') +
|
||
'v' + m.releaseId +
|
||
(date ? ' · built ' + date : '') +
|
||
' · hash ' + shortHash;
|
||
|
||
pills.forEach(function (el) {
|
||
var linkHref = el.getAttribute('data-link') || '#release';
|
||
var a = document.createElement('a');
|
||
a.href = linkHref;
|
||
a.title = title;
|
||
a.setAttribute('aria-label',
|
||
'Release v' + m.releaseId + (date ? ', built ' + date : ''));
|
||
var v = document.createElement('span');
|
||
v.className = 'release-pill-version';
|
||
v.textContent = 'v' + m.releaseId;
|
||
a.appendChild(v);
|
||
if (date) {
|
||
var d = document.createElement('span');
|
||
d.className = 'release-pill-date';
|
||
d.textContent = ' · ' + date;
|
||
a.appendChild(d);
|
||
}
|
||
el.innerHTML = '';
|
||
el.appendChild(a);
|
||
});
|
||
})
|
||
.catch(function () { /* silent: best-effort chrome */ });
|
||
})();
|
||
</script>
|
||
|
||
|
||
|
||
|
||
</body></html> |