Files
cs249r_book/site/index.qmd
Vijay Janapa Reddi 1499c0d58f refactor: move volumes to top-level /vol1/ and /vol2/ URLs
The project's source convention (navbar, footer, announcements,
instructor course-map, etc.) already treats mlsysbook.ai/vol1/ and
mlsysbook.ai/vol2/ as the canonical URLs. The /book/vol1/ nesting was
an artifact of the legacy single-volume textbook still occupying /book/
on live, kept alive by a special-case mapping in the dev URL rewriter.
This refactor aligns the actual deploy paths with the source convention
before Monday's release locks in citation-grade URLs.

Public URL change:
  was:   https://mlsysbook.ai/book/vol1/  + .../book/vol2/
  is:    https://mlsysbook.ai/vol1/       + .../vol2/

Variable change (set on harvard-edge/cs249r_book):
  VOL1_DEPLOY_PATH=vol1   (new)
  VOL2_DEPLOY_PATH=vol2   (new)
  BOOK_DEPLOY_PATH=book   (will be deleted post-merge)

Workflow changes:

  book-publish-live.yml
    - Reads VOL1_DEPLOY_PATH + VOL2_DEPLOY_PATH (fail-fast on empty).
    - Each volume deploys to its own top-level path on gh-pages.
    - Skip-list regex now includes both top-level paths plus 'book' so
      the legacy single-volume textbook at /book/ stays untouched
      (the user-facing front door remains the OLD textbook until an
      explicit cutover via the Cloudflare redirect).
    - Root index.html redirect now targets /$VOL1_PATH/ instead of
      /$BOOK_PATH/vol1/. The CF redirect is what users see; this is
      a fallback only.
    - Validation, commit message, and step summary lines log both
      volume paths separately rather than a single book parent.

  book-preview-dev.yml
    - Same VOL1/VOL2 read with fail-fast guard.
    - Cleans /vol1/, /vol2/, AND legacy /book/ on the dev preview repo
      to avoid zombie content from the previous nested deploy.
    - Copies preview-site/vol1 → /vol1/ and preview-site/vol2 → /vol2/
      separately (no longer wraps both under /book/).
    - Drops the /book/ chooser page on dev (the dev landing page
      already has volume cards). The chooser file stays in the repo
      for the eventual live cutover.

  publish-all-live.yml
    - Step summary now lists Volume I and Volume II as separate links.

  rewrite-dev-urls.sh
    - vol1 → vol1, vol2 → vol2 (identity mapping; matches every other
      subsite). The PREFIX depth math stays generic for any future
      nested subsite.

  site/index.qmd
    - Volume cards link to vol1/ and vol2/ (top-level relative). On
      live this resolves to mlsysbook.ai/vol1/ and mlsysbook.ai/vol2/.

Result: zero asymmetry between the volume URL convention used in source
and the actual deploy paths. The dev URL rewriter no longer needs a
special case. Citations made against Monday's release URLs will be
permanent and aligned with the project's everyday URL vocabulary.
2026-04-25 19:20:02 -04:00

471 lines
34 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "Machine Learning Systems"
format:
html:
toc: false
page-layout: full
title-block: none
css:
- landing.css
- landing-v3.css
---
::: {.content-visible when-format="html"}
```{=html}
<div id="mls-neural-bg" aria-hidden="true"></div>
<div class="mls-landing mls-landing-v3">
<!-- ═══ Snap 1: The Textbook ═══ -->
<section class="mls-section mls-section-hero">
<div class="mls-landing-grid">
<div class="mls-landing-left">
<p class="mls-hero-eyebrow">TWO-VOLUME TEXTBOOK</p>
<h1 class="mls-hero-title">Machine Learning<br/>Systems.</h1>
<p class="mls-hero-tagline">The physics of AI engineering.</p>
<p class="mls-hero-intro">A rigorous, principles-first treatment of how ML systems are built, optimized, and deployed — from a single machine to fleet-scale infrastructure.</p>
<p class="mls-hero-badge">Harvard University &middot; MIT Press 2026</p>
<p class="mls-hero-edition">
<span class="mls-edition-dot" aria-hidden="true"></span>
<span>Actively maintained</span>
<span class="mls-edition-sep" aria-hidden="true">&middot;</span>
<span>Last updated <span id="mls-edition-date">April 2026</span></span>
<span class="mls-edition-sep" aria-hidden="true">&middot;</span>
<a href="https://github.com/harvard-edge/cs249r_book/releases" target="_blank" rel="noopener" class="mls-edition-link">Release notes</a>
</p>
</div>
<div class="mls-landing-right">
<div class="mls-volumes">
<div class="mls-vol-card">
<a href="vol1/" class="mls-vol-card-link" title="Open Volume I">
<span class="mls-vol-cover-wrap"><img src="covers/cover-hardcover-book-vol1.png" alt="Volume I cover" class="mls-vol-cover" loading="lazy" /></span>
<p class="mls-vol-title">Volume I</p>
<p class="mls-vol-subtitle">Introduction to Machine Learning Systems</p>
</a>
<p class="mls-vol-downloads">
<span class="visually-hidden">Volume I downloads:</span>
<a href="vol1/" target="_blank" rel="noopener">HTML</a>
<a href="vol1/assets/downloads/Machine-Learning-Systems-Vol1.pdf" target="_blank" rel="noopener">PDF</a>
<a href="vol1/assets/downloads/Machine-Learning-Systems-Vol1.epub" target="_blank" rel="noopener">EPUB</a>
</p>
</div>
<div class="mls-vol-card">
<a href="vol2/" class="mls-vol-card-link" title="Open Volume II">
<span class="mls-vol-cover-wrap"><img src="covers/cover-hardcover-book-vol2.png" alt="Volume II cover" class="mls-vol-cover" loading="lazy" /></span>
<p class="mls-vol-title">Volume II</p>
<p class="mls-vol-subtitle">Machine Learning Systems at Scale</p>
</a>
<p class="mls-vol-downloads">
<span class="visually-hidden">Volume II downloads:</span>
<a href="vol2/" target="_blank" rel="noopener">HTML</a>
<a href="vol2/assets/downloads/Machine-Learning-Systems-Vol2.pdf" target="_blank" rel="noopener">PDF</a>
<a href="vol2/assets/downloads/Machine-Learning-Systems-Vol2.epub" target="_blank" rel="noopener">EPUB</a>
</p>
</div>
</div>
</div>
</div>
<div class="mls-scroll-indicator" role="button" tabindex="0" aria-label="Scroll to curriculum section">
<span>Explore the Curriculum</span>
<div class="mls-scroll-arrow">&darr;</div>
</div>
</section>
<!-- ═══ Snap 2: The Curriculum — Rich Cards ═══ -->
<section class="mls-section mls-section-richcards" id="curriculum">
<div class="mls-cards-header">
<h2 class="mls-cards-title">A complete curriculum for AI engineering.</h2>
<p style="margin: 0.45rem auto 0; max-width: 760px; color: var(--mls-muted); font-size: 0.95rem;">Choose a path: read the books, explore trade-offs in labs, build the internals with TinyTorch, model constraints with MLSys·im, deploy on real hardware, practice with StaffML, or adopt the full course with the Blueprint.</p>
</div>
<div class="mls-rich-grid">
<!-- Row label: Students & Learners -->
<p class="mls-row-label">For Students &amp; Learners</p>
<!-- Labs -->
<a href="labs/" class="mls-rich-card" data-accent="explore">
<div class="mls-rich-card-info">
<p class="mls-cur-verb">EXPLORE</p>
<h3 class="mls-cur-name">Labs</h3>
<p class="mls-cur-desc">Interactive Marimo notebooks. Change a parameter, see what breaks, build intuition.</p>
</div>
<div class="mls-rich-card-demo">
<svg viewBox="0 0 300 170" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice">
<rect width="300" height="170" fill="#eef2f7"/>
<!-- Header bar -->
<rect width="300" height="22" fill="#dce6f0"/>
<text x="10" y="15" font-size="8.5" fill="#2d6da3" font-weight="700" font-family="Inter,Helvetica,sans-serif">Lab 15 · Sustainable AI</text>
<rect x="248" y="5" width="44" height="12" rx="6" fill="#2d6da3" opacity="0.15"/>
<text x="270" y="14.5" font-size="6.5" fill="#2d6da3" text-anchor="middle" font-weight="600" font-family="Inter,Helvetica,sans-serif">Explore</text>
<!-- Map shifted down by 20 -->
<g transform="translate(0,20)">
<path d="M0.0,17.5L8.4,20.0L5.9,21.5L0.1,20.1L300.0,20.9L297.8,21.2L299.4,23.1L286.3,25.1L285.1,29.3L280.7,32.5L279.9,27.7L287.1,22.9L283.4,24.5L280.6,23.8L279.2,25.7L268.5,25.8L262.6,29.4L266.6,29.8L267.8,31.5L264.1,37.4L256.3,41.9L257.6,45.8L255.4,46.3L254.4,42.0L250.9,42.6L251.4,40.9L248.4,42.3L249.1,43.8L252.0,43.8L249.3,45.9L251.6,48.6L251.4,51.5L246.6,56.0L238.2,58.5L241.1,63.8L238.7,67.1L237.6,67.8L233.4,63.8L232.7,67.3L236.9,73.9L232.0,68.5L231.0,60.9L228.5,61.6L226.2,56.0L222.5,57.1L216.9,61.8L216.5,66.4L214.6,68.4L210.5,57.2L208.7,57.6L205.3,53.8L197.8,53.6L190.0,50.0L193.2,55.0L197.0,53.0L199.8,56.4L195.7,60.9L186.2,64.5L179.1,50.4L178.3,52.0L177.0,50.1L181.2,59.5L185.6,65.2L187.2,66.3L192.6,65.0L192.5,66.1L190.5,70.6L182.7,78.9L184.0,87.2L179.0,91.5L179.7,94.8L177.1,96.4L177.1,98.6L172.9,102.7L166.3,104.0L159.8,90.1L161.4,83.9L157.3,75.9L158.2,72.4L153.6,69.8L142.5,71.0L136.1,64.7L135.8,57.1L145.1,45.2L157.9,43.9L159.3,44.2L158.6,46.8L165.9,49.8L168.0,47.6L178.1,49.2L180.1,44.5L173.0,44.5L171.8,42.1L177.9,40.0L184.8,40.0L180.6,37.3L182.6,35.6L178.2,38.0L175.6,36.2L173.1,39.5L174.0,40.8L169.0,41.3L170.0,43.6L168.7,44.7L166.3,40.2L161.0,36.9L160.5,38.3L165.4,41.5L164.1,41.3L163.4,43.3L157.4,38.0L152.6,39.1L148.2,44.4L142.6,44.3L142.2,39.1L148.8,38.3L149.0,36.7L146.2,34.4L156.8,30.4L157.1,27.4L158.8,26.9L159.1,30.0L166.4,29.6L168.0,27.2L170.1,27.5L169.5,25.7L174.3,25.0L167.8,24.4L167.9,22.3L171.2,20.7L168.5,20.2L164.9,22.7L165.7,24.9L163.2,28.2L160.8,28.9L158.6,25.4L154.7,26.2L154.9,22.8L170.5,15.8L184.2,18.8L177.7,19.5L180.8,21.8L186.6,19.9L186.2,17.9L188.5,18.1L188.6,19.4L194.8,17.6L200.0,18.1L200.5,16.8L207.1,18.3L205.6,15.8L208.3,14.1L210.7,14.8L211.4,18.0L209.4,19.7L210.4,19.9L212.5,18.5L210.9,15.5L212.2,14.3L212.7,15.6L217.9,15.2L217.1,13.6L237.0,10.3L245.1,11.8L241.2,13.2L255.8,13.7L259.4,16.0L267.1,14.3L291.3,17.8L292.0,16.6L298.8,17.2L0.0,17.5Z M74.5,17.1L77.2,19.0L78.7,16.8L81.1,17.0L82.3,18.7L72.4,23.3L71.1,25.9L73.1,27.4L81.4,29.0L83.4,32.3L84.5,31.2L83.5,29.4L86.2,27.9L84.6,26.0L84.9,23.1L88.5,23.0L92.0,24.1L93.6,26.5L96.2,24.7L103.6,31.5L94.7,33.1L90.7,36.0L95.8,34.0L96.3,36.5L100.2,36.7L95.5,38.7L96.3,37.3L94.1,37.4L91.1,39.1L91.7,40.3L87.1,42.1L86.7,44.0L86.4,42.4L86.9,45.4L82.2,48.8L83.0,54.0L79.9,49.9L71.8,50.2L69.0,51.8L68.4,56.3L69.8,58.9L72.7,59.6L77.5,57.0L75.9,61.8L80.7,62.5L80.1,65.5L81.5,67.5L86.0,67.8L90.2,64.6L90.3,67.4L91.7,64.9L93.2,66.2L98.4,66.1L102.4,70.0L107.2,71.5L108.0,75.1L116.7,77.4L121.1,81.1L117.5,86.5L115.9,93.3L110.3,95.7L105.2,103.7L101.3,103.3L102.7,105.3L101.9,106.8L95.7,109.2L97.1,110.5L93.9,113.0L95.0,115.1L90.8,119.9L87.5,118.6L88.2,114.1L87.0,113.9L89.4,110.3L88.1,111.0L91.4,90.3L86.7,87.2L82.3,80.1L82.6,75.9L85.7,71.8L84.5,67.7L82.6,69.0L78.6,66.7L77.1,63.9L63.8,59.8L54.4,48.5L58.8,55.7L56.5,54.4L46.3,41.4L46.1,34.8L47.8,35.8L47.6,34.2L43.8,32.6L38.3,26.6L27.4,24.3L23.6,25.7L24.5,23.9L18.0,28.3L12.7,29.7L19.1,25.9L15.0,26.1L11.6,23.8L16.0,21.0L9.9,20.3L15.3,19.9L11.0,18.0L19.5,15.5L36.2,17.6L46.3,16.5L59.3,18.8L61.5,17.7L69.9,18.9L71.5,17.4L69.6,16.6L70.7,15.1L74.5,17.1Z M0.0,145.6L30.7,145.9L22.0,144.7L22.6,143.4L19.3,142.6L28.0,141.9L20.6,140.9L18.0,139.1L23.9,139.5L28.2,137.8L55.0,136.4L66.1,137.8L63.6,135.5L93.4,135.7L93.5,131.1L101.8,127.7L95.3,131.6L98.5,133.9L98.9,136.8L85.6,138.9L88.6,139.9L85.0,141.0L101.5,144.3L126.2,141.9L120.2,140.3L135.4,137.6L144.3,134.1L172.6,133.7L178.2,132.1L182.2,133.1L195.4,129.8L207.4,131.6L206.6,134.9L208.2,135.2L223.3,130.2L229.8,131.2L235.7,129.6L238.5,130.8L244.7,129.9L249.9,131.1L262.6,129.4L264.6,130.8L292.7,134.7L286.3,138.5L289.2,140.6L283.2,142.5L298.6,145.4L0.0,145.6Z M269.6,86.5L277.6,96.7L277.6,100.8L275.0,106.2L271.9,107.5L267.2,106.7L265.2,103.7L264.0,104.4L264.8,102.4L263.3,104.1L259.4,101.2L248.4,104.2L245.9,103.5L245.1,93.1L250.7,91.4L255.1,86.7L258.0,87.5L259.9,84.4L263.7,84.9L262.9,87.5L266.8,89.8L268.8,83.9L269.6,86.5Z M127.4,5.4L132.6,6.1L123.4,6.5L139.8,7.3L133.3,8.2L135.2,8.2L133.6,9.4L134.6,10.8L131.9,11.1L133.9,13.1L129.3,14.7L131.9,16.1L128.0,16.5L131.4,16.6L116.8,20.5L113.9,24.9L109.8,24.3L107.0,22.0L105.0,19.0L107.6,16.7L104.4,17.0L107.2,16.2L103.5,15.3L104.4,14.5L101.2,12.1L88.9,10.0L99.8,6.6L127.4,5.4Z" class="lab-map-land" fill="#b8d4e8" stroke="#4a90c4" stroke-width="0.5"/>
<!-- Datacenter dots -->
<circle cx="158" cy="23" r="3" fill="#64748b" stroke="#fff" stroke-width="1" opacity="0.5"/>
<circle cx="152" cy="34" r="3" fill="#64748b" stroke="#fff" stroke-width="1" opacity="0.5"/>
<circle cx="236" cy="74" r="3" fill="#64748b" stroke="#fff" stroke-width="1" opacity="0.5"/>
<circle cx="72" cy="40" r="3" fill="#64748b" stroke="#fff" stroke-width="1" opacity="0.5"/>
<circle cx="211" cy="59" r="3" fill="#64748b" stroke="#fff" stroke-width="1" opacity="0.5"/>
<circle cx="167" cy="32" r="3" fill="#64748b" stroke="#fff" stroke-width="1" opacity="0.5"/>
<!-- Animated active dot -->
<circle r="5" stroke="#fff" stroke-width="1.5">
<animate attributeName="cx" values="158;158;152;152;236;236;72;72;211;211;167;167;158" keyTimes="0;0.14;0.167;0.31;0.333;0.48;0.5;0.64;0.667;0.81;0.833;0.97;1" dur="15s" repeatCount="indefinite"/>
<animate attributeName="cy" values="23;23;34;34;74;74;40;40;59;59;32;32;23" keyTimes="0;0.14;0.167;0.31;0.333;0.48;0.5;0.64;0.667;0.81;0.833;0.97;1" dur="15s" repeatCount="indefinite"/>
<animate attributeName="fill" values="#2d8a4e;#2d8a4e;#3d9e5a;#3d9e5a;#d4a017;#d4a017;#c87b2a;#c87b2a;#c44;#c44;#e05252;#e05252;#2d8a4e" keyTimes="0;0.14;0.167;0.31;0.333;0.48;0.5;0.64;0.667;0.81;0.833;0.97;1" dur="15s" repeatCount="indefinite"/>
</circle>
<!-- Pulse ring -->
<circle fill="none" stroke-width="1.5" opacity="0">
<animate attributeName="cx" values="158;158;152;152;236;236;72;72;211;211;167;167;158" keyTimes="0;0.14;0.167;0.31;0.333;0.48;0.5;0.64;0.667;0.81;0.833;0.97;1" dur="15s" repeatCount="indefinite"/>
<animate attributeName="cy" values="23;23;34;34;74;74;40;40;59;59;32;32;23" keyTimes="0;0.14;0.167;0.31;0.333;0.48;0.5;0.64;0.667;0.81;0.833;0.97;1" dur="15s" repeatCount="indefinite"/>
<animate attributeName="stroke" values="#2d8a4e;#2d8a4e;#3d9e5a;#3d9e5a;#d4a017;#d4a017;#c87b2a;#c87b2a;#c44;#c44;#e05252;#e05252;#2d8a4e" keyTimes="0;0.14;0.167;0.31;0.333;0.48;0.5;0.64;0.667;0.81;0.833;0.97;1" dur="15s" repeatCount="indefinite"/>
<animate attributeName="r" values="5;20;5" dur="1.5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.6;0;0.6" dur="1.5s" repeatCount="indefinite"/>
</circle>
</g>
</svg>
</div>
</a>
<!-- TinyTorch -->
<a href="tinytorch/" class="mls-rich-card" data-accent="build">
<div class="mls-rich-card-info">
<p class="mls-cur-verb">BUILD</p>
<h3 class="mls-cur-name">TinyTorch</h3>
<p class="mls-cur-desc">Build your own ML framework from scratch across 20 progressive modules. Zero magic.</p>
</div>
<div class="mls-rich-card-demo">
<svg viewBox="0 0 260 140" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice">
<defs>
<!-- Clip paths that expand to reveal each line like typing -->
<clipPath id="tt-l3"><rect x="40" y="62" width="0" height="14"><animate attributeName="width" from="0" to="220" dur="0.6s" begin="1s" fill="freeze"/></rect></clipPath>
<clipPath id="tt-l4"><rect x="40" y="78" width="0" height="14"><animate attributeName="width" from="0" to="220" dur="0.7s" begin="1.8s" fill="freeze"/></rect></clipPath>
<clipPath id="tt-l5"><rect x="40" y="94" width="0" height="14"><animate attributeName="width" from="0" to="220" dur="0.9s" begin="2.8s" fill="freeze"/></rect></clipPath>
</defs>
<!-- Terminal fills entire card -->
<rect width="260" height="140" fill="#1e1e2e"/>
<!-- Title bar -->
<rect width="260" height="22" fill="#2a2a3a"/>
<circle cx="14" cy="11" r="4" fill="#ff5f57"/>
<circle cx="26" cy="11" r="4" fill="#febc2e"/>
<circle cx="38" cy="11" r="4" fill="#28c840"/>
<text x="130" y="14" font-size="7" fill="#666" text-anchor="middle" font-family="monospace">tinytorch — tensor.py</text>
<!-- Static lines (already typed) -->
<text x="12" y="40" font-size="9" font-family="monospace"><tspan fill="#c586c0">class</tspan><tspan fill="#ddd"> </tspan><tspan fill="#4ec9b0">Tensor</tspan><tspan fill="#ddd">:</tspan></text>
<text x="26" y="56" font-size="9" font-family="monospace"><tspan fill="#c586c0">def</tspan><tspan fill="#ddd"> </tspan><tspan fill="#dcdcaa">__init__</tspan><tspan fill="#ddd">(self, data):</tspan></text>
<!-- Typing lines (revealed by expanding clip-path) -->
<text x="40" y="72" font-size="9" font-family="monospace" clip-path="url(#tt-l3)"><tspan fill="#ddd">self.data = data</tspan></text>
<text x="40" y="88" font-size="9" font-family="monospace" clip-path="url(#tt-l4)"><tspan fill="#ddd">self.grad = </tspan><tspan fill="#b5cea8">0.0</tspan></text>
<text x="40" y="104" font-size="9" font-family="monospace" clip-path="url(#tt-l5)"><tspan fill="#ddd">self._backward = </tspan><tspan fill="#c586c0">lambda</tspan><tspan fill="#ddd">: </tspan><tspan fill="#569cd6">None</tspan></text>
<!-- Cursor moves down as lines type -->
<rect width="6" height="11" fill="#a56520">
<animate attributeName="x" values="26;26;40;40;40;40;12" keyTimes="0;0.15;0.2;0.4;0.55;0.9;0.95" dur="4.5s" fill="freeze"/>
<animate attributeName="y" values="58;58;62;78;94;112;112" keyTimes="0;0.15;0.2;0.4;0.55;0.9;0.95" dur="4.5s" fill="freeze"/>
<animate attributeName="opacity" values="1;0;1" dur="0.8s" repeatCount="indefinite"/>
</rect>
</svg>
</div>
</a>
<!-- MLSys-im -->
<a href="mlsysim/" class="mls-rich-card" data-accent="model">
<div class="mls-rich-card-info">
<p class="mls-cur-verb">MODEL</p>
<h3 class="mls-cur-name">MLSys&middot;im</h3>
<p class="mls-cur-desc">First-principles performance modeling. One command, every bottleneck.</p>
</div>
<div class="mls-rich-card-demo">
<svg viewBox="0 0 260 140" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice">
<rect width="260" height="140" fill="#cce8f9"/>
<!-- CLI bar -->
<rect width="260" height="24" fill="#0284C7"/>
<text x="10" y="16" font-size="8" font-family="monospace"><tspan fill="#fff" font-weight="700">$ mlsysim</tspan><tspan fill="#bae6fd"> eval</tspan><tspan fill="#e0f2fe"> Llama3_70B H100</tspan><tspan fill="#7dd3fc"> --batch-size </tspan><tspan fill="#fbbf24" font-weight="600">1</tspan></text>
<!-- Axes -->
<line x1="30" y1="126" x2="248" y2="126" stroke="#0284C7" stroke-width="1" opacity="0.3"/>
<line x1="30" y1="126" x2="30" y2="34" stroke="#0284C7" stroke-width="1" opacity="0.3"/>
<!-- Roofline curve -->
<path d="M30,114 L120,52 L248,52" fill="none" stroke="#0369a1" stroke-width="2.5" opacity="0.7"/>
<!-- Shaded region -->
<path d="M30,114 L120,52 L248,52 L248,126 L30,126 Z" fill="#0284C7" opacity="0.08"/>
<!-- Ridge line -->
<line x1="120" y1="52" x2="120" y2="126" stroke="#0284C7" stroke-width="0.8" stroke-dasharray="4,3" opacity="0.25"/>
<!-- Animated workload dot -->
<circle r="6" stroke="#fff" stroke-width="1.5">
<animate attributeName="cx" values="65;65;120;120;200;200;65" keyTimes="0;0.28;0.33;0.61;0.66;0.95;1" dur="9s" repeatCount="indefinite"/>
<animate attributeName="cy" values="88;88;52;52;52;52;88" keyTimes="0;0.28;0.33;0.61;0.66;0.95;1" dur="9s" repeatCount="indefinite"/>
<animate attributeName="fill" values="#c87b2a;#c87b2a;#3d9e5a;#3d9e5a;#e05252;#e05252;#c87b2a" keyTimes="0;0.28;0.33;0.61;0.66;0.95;1" dur="9s" repeatCount="indefinite"/>
</circle>
<!-- Region labels -->
<text x="50" y="106" font-size="7.5" fill="#0284C7" font-family="Inter,sans-serif" opacity="0.4">mem-bound</text>
<text x="168" y="70" font-size="7.5" fill="#0284C7" font-family="Inter,sans-serif" opacity="0.4">compute-bound</text>
<!-- Batch labels -->
<text x="73" y="82" fill="#c87b2a" font-size="8" font-weight="600" font-family="Inter,sans-serif" opacity="0.8">b=1</text>
<text x="128" y="46" fill="#3d9e5a" font-size="8" font-weight="600" font-family="Inter,sans-serif" opacity="0.8">b=32</text>
<text x="208" y="46" fill="#e05252" font-size="8" font-weight="600" font-family="Inter,sans-serif" opacity="0.8">b=128</text>
<!-- Axis labels -->
<text x="140" y="138" font-size="7" fill="#0284C7" font-family="Inter,sans-serif" opacity="0.35" text-anchor="middle">Arithmetic Intensity</text>
<text x="17" y="82" font-size="7" fill="#0284C7" font-family="Inter,sans-serif" opacity="0.35" transform="rotate(-90,17,82)">FLOP/s</text>
</svg>
</div>
</a>
<!-- Hardware Kits -->
<a href="kits/" class="mls-rich-card" data-accent="deploy">
<div class="mls-rich-card-info">
<p class="mls-cur-verb">DEPLOY</p>
<h3 class="mls-cur-name">Hardware Kits</h3>
<p class="mls-cur-desc">Deploy ML to Arduino, Seeed, Grove, and Raspberry Pi. Real memory limits, real power budgets.</p>
</div>
<div class="mls-rich-card-demo">
<svg viewBox="0 0 260 140" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice">
<rect width="260" height="140" fill="#c8ebe3"/>
<!-- Header banner -->
<rect width="260" height="22" fill="#148F77"/>
<text x="10" y="15" font-size="8" fill="#fff" font-weight="700" font-family="Inter,sans-serif">Arduino · Seeed · Grove · Raspberry Pi</text>
<!-- Board image area -->
<image href="assets/nicla-vision-both-transparent.png" x="30" y="28" width="200" height="106" preserveAspectRatio="xMidYMid meet"/>
</svg>
</div>
</a>
<!-- Row label: Career & Instructors -->
<p class="mls-row-label">For Career &amp; Instructors</p>
<!-- StaffML -->
<a href="staffml/" class="mls-rich-card" data-accent="practice">
<div class="mls-rich-card-info">
<p class="mls-cur-verb">PRACTICE</p>
<h3 class="mls-cur-name">StaffML</h3>
<p class="mls-cur-desc">Physics-grounded interview questions for ML systems roles. Vault, drills, and mock interviews.</p>
</div>
<div class="mls-rich-card-demo">
<svg viewBox="0 0 260 140" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice">
<rect width="260" height="140" fill="#e8edf3"/>
<!-- Header band -->
<rect width="260" height="24" fill="#334155"/>
<text x="10" y="16" font-size="8" fill="#fff" font-weight="700" font-family="Inter,sans-serif">Systems Design</text>
<text x="250" y="16" font-size="7.5" fill="#94a3b8" font-family="Inter,sans-serif" text-anchor="end">L5 · Staff</text>
<!-- Question -->
<text x="14" y="42" font-size="8" fill="#1e293b" font-weight="600" font-family="Inter,sans-serif">A 70B model needs 1,000 req/s.</text>
<text x="14" y="54" font-size="7.5" fill="#475569" font-family="Inter,sans-serif">Walk through your hardware selection</text>
<text x="14" y="65" font-size="7.5" fill="#475569" font-family="Inter,sans-serif">and parallelism strategy.</text>
<!-- Rubric bars — thicker, clearer -->
<text x="14" y="82" font-size="6.5" fill="#64748b" font-weight="600" font-family="Inter,sans-serif">Hardware</text>
<rect x="70" y="76" width="170" height="7" rx="3.5" fill="#e2e8f0"/><rect x="70" y="76" width="144" height="7" rx="3.5" fill="#4a90c4"/>
<text x="14" y="96" font-size="6.5" fill="#64748b" font-weight="600" font-family="Inter,sans-serif">Parallelism</text>
<rect x="70" y="90" width="170" height="7" rx="3.5" fill="#e2e8f0"/><rect x="70" y="90" width="153" height="7" rx="3.5" fill="#3d9e5a"/>
<text x="14" y="110" font-size="6.5" fill="#64748b" font-weight="600" font-family="Inter,sans-serif">Trade-offs</text>
<rect x="70" y="104" width="170" height="7" rx="3.5" fill="#e2e8f0"/><rect x="70" y="104" width="127" height="7" rx="3.5" fill="#c87b2a"/>
<!-- Domain tags at bottom -->
<rect x="10" y="120" width="36" height="14" rx="7" fill="#e3f2fd"/>
<text x="28" y="130" font-size="6.5" fill="#4a90c4" text-anchor="middle" font-weight="600" font-family="Inter,sans-serif">Cloud</text>
<rect x="50" y="120" width="30" height="14" rx="7" fill="#e8f5e9"/>
<text x="65" y="130" font-size="6.5" fill="#2d7a2d" text-anchor="middle" font-weight="600" font-family="Inter,sans-serif">Edge</text>
<rect x="84" y="120" width="36" height="14" rx="7" fill="#fff3e0"/>
<text x="102" y="130" font-size="6.5" fill="#c87b2a" text-anchor="middle" font-weight="600" font-family="Inter,sans-serif">Mobile</text>
<rect x="124" y="120" width="40" height="14" rx="7" fill="#fce4ec"/>
<text x="144" y="130" font-size="6.5" fill="#c44" text-anchor="middle" font-weight="600" font-family="Inter,sans-serif">TinyML</text>
</svg>
</div>
</a>
<!-- Instructor Hub -->
<a href="instructors/" class="mls-rich-card" data-accent="adopt">
<div class="mls-rich-card-info">
<p class="mls-cur-verb">ADOPT</p>
<h3 class="mls-cur-name">Instructor Hub</h3>
<p class="mls-cur-desc">The AI Engineering Blueprint: two-semester syllabi, pedagogy guide, rubrics, and TA handbook.</p>
</div>
<div class="mls-rich-card-demo">
<svg viewBox="0 0 260 140" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice">
<rect width="260" height="140" fill="#e8e8f4"/>
<!-- Blueprint grid lines -->
<line x1="0" y1="32" x2="260" y2="32" stroke="#6366f1" stroke-width="0.3" opacity="0.1"/>
<line x1="0" y1="66" x2="260" y2="66" stroke="#6366f1" stroke-width="0.3" opacity="0.1"/>
<line x1="0" y1="100" x2="260" y2="100" stroke="#6366f1" stroke-width="0.3" opacity="0.1"/>
<line x1="130" y1="0" x2="130" y2="140" stroke="#6366f1" stroke-width="0.3" opacity="0.1"/>
<!-- Title block -->
<text x="130" y="14" font-size="9" fill="#333" text-anchor="middle" font-weight="700" font-family="Inter,sans-serif">The Blueprint — Course Architecture</text>
<text x="130" y="25" font-size="7" fill="#6366f1" text-anchor="middle" font-family="Inter,sans-serif" opacity="0.6">ML Systems · Two-Semester Curriculum</text>
<!-- Module boxes: 2×2 grid -->
<rect x="8" y="34" width="118" height="28" rx="4" fill="#e0e0f0" stroke="#6366f1" stroke-width="0.8"/>
<text x="16" y="46" font-size="7" fill="#333" font-weight="700" font-family="Inter,sans-serif">Semester 1: Foundations</text>
<text x="16" y="56" font-size="6" fill="#555" font-family="Inter,sans-serif" opacity="0.7">16 wks · Vol I · 8 assignments</text>
<rect x="134" y="34" width="118" height="28" rx="4" fill="#e0e0f0" stroke="#6366f1" stroke-width="0.8"/>
<text x="142" y="46" font-size="7" fill="#333" font-weight="700" font-family="Inter,sans-serif">Semester 2: At Scale</text>
<text x="142" y="56" font-size="6" fill="#555" font-family="Inter,sans-serif" opacity="0.7">16 wks · Vol II · capstone</text>
<rect x="8" y="68" width="118" height="28" rx="4" fill="#ebebf7" stroke="#6366f1" stroke-width="0.8"/>
<text x="16" y="80" font-size="7" fill="#333" font-weight="700" font-family="Inter,sans-serif">Assessment</text>
<text x="16" y="90" font-size="6" fill="#555" font-family="Inter,sans-serif" opacity="0.7">Rubrics · Peer review · Grading</text>
<rect x="134" y="68" width="118" height="28" rx="4" fill="#ebebf7" stroke="#6366f1" stroke-width="0.8"/>
<text x="142" y="80" font-size="7" fill="#333" font-weight="700" font-family="Inter,sans-serif">Teaching Staff</text>
<text x="142" y="90" font-size="6" fill="#555" font-family="Inter,sans-serif" opacity="0.7">Pedagogy · TA handbook</text>
<!-- Stamp -->
<rect x="185" y="104" width="60" height="24" rx="4" fill="none" stroke="#6366f1" stroke-width="1.5" stroke-dasharray="3,2" opacity="0.4" transform="rotate(-5,215,116)"/>
<text x="215" y="119" font-size="8" fill="#6366f1" text-anchor="middle" font-weight="700" font-family="Inter,sans-serif" opacity="0.4" transform="rotate(-5,215,119)">READY</text>
</svg>
</div>
</a>
<!-- Row 4 -->
<!-- Lecture Slides -->
<a href="slides/" class="mls-rich-card" data-accent="teach">
<div class="mls-rich-card-info">
<p class="mls-cur-verb">TEACH</p>
<h3 class="mls-cur-name">Lecture Slides</h3>
<p class="mls-cur-desc">35 Beamer decks with speaker notes and 266 original SVG diagrams. Drop in and teach.</p>
</div>
<div class="mls-rich-card-demo">
<svg viewBox="0 0 260 140" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice">
<rect width="260" height="140" fill="#fff"/>
<!-- Top nav bar -->
<rect width="260" height="18" fill="#a31f34"/>
<text x="10" y="12" font-size="6" fill="#fff" font-family="Inter,sans-serif" opacity="0.5">Intro</text>
<text x="34" y="12" font-size="6" fill="#fff" font-family="Inter,sans-serif" opacity="0.5">Systems</text>
<text x="68" y="12" font-size="6" fill="#fff" font-family="Inter,sans-serif" opacity="0.5">DNN</text>
<rect x="87" y="3" width="40" height="12" rx="2" fill="#fff" opacity="0.2"/>
<text x="107" y="12" font-size="6" fill="#fff" font-family="Inter,sans-serif" font-weight="700" text-anchor="middle">Training</text>
<text x="140" y="12" font-size="6" fill="#fff" font-family="Inter,sans-serif" opacity="0.5">Accel</text>
<text x="168" y="12" font-size="6" fill="#fff" font-family="Inter,sans-serif" opacity="0.5">Deploy</text>
<text x="198" y="12" font-size="6" fill="#fff" font-family="Inter,sans-serif" opacity="0.5">Ethics</text>
<!-- Slide title -->
<text x="16" y="36" font-size="10" fill="#1a202c" font-weight="700" font-family="Inter,sans-serif">The Iron Law of ML Systems</text>
<!-- Equation -->
<rect x="16" y="43" width="228" height="18" rx="3" fill="#edf2f7"/>
<text x="130" y="56" font-size="10" fill="#2d3748" text-anchor="middle" font-family="monospace" font-weight="600">T = D/BW + O/(R·η) + L</text>
<!-- Bullet points -->
<circle cx="20" cy="73" r="2" fill="#4a90c4"/>
<text x="28" y="76" font-size="7" fill="#4a5568" font-family="Inter,sans-serif"><tspan font-weight="600" fill="#1a202c">Data Term</tspan> — memory bandwidth</text>
<circle cx="20" cy="88" r="2" fill="#3d9e5a"/>
<text x="28" y="91" font-size="7" fill="#4a5568" font-family="Inter,sans-serif"><tspan font-weight="600" fill="#1a202c">Compute Term</tspan> — utilization η ≤ 0.7</text>
<circle cx="20" cy="103" r="2" fill="#c87b2a"/>
<text x="28" y="106" font-size="7" fill="#4a5568" font-family="Inter,sans-serif"><tspan font-weight="600" fill="#1a202c">Latency Term</tspan> — orchestration overhead</text>
<!-- Footer -->
<rect y="122" width="260" height="18" fill="#f7fafc"/>
<text x="10" y="134" font-size="6" fill="#a0aec0" font-family="Inter,sans-serif">Harvard University · ML Systems</text>
<text x="250" y="134" font-size="6" fill="#a0aec0" font-family="Inter,sans-serif" text-anchor="end">12 / 38</text>
</svg>
</div>
</a>
<!-- Newsletter -->
<a href="newsletter/" class="mls-rich-card" data-accent="follow">
<div class="mls-rich-card-info">
<p class="mls-cur-verb">FOLLOW</p>
<h3 class="mls-cur-name">Newsletter</h3>
<p class="mls-cur-desc">Updates on the curriculum, new chapters, and what the community is building.</p>
</div>
<div class="mls-rich-card-demo">
<svg viewBox="0 0 260 140" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice">
<rect width="260" height="140" fill="#f4f5f7"/>
<!-- Header -->
<rect width="260" height="26" fill="#e2e5ea"/>
<text x="16" y="18" font-size="9.5" fill="#1e293b" font-weight="700" font-family="Inter,sans-serif">MLSysBook Weekly</text>
<circle cx="240" cy="13" r="5" fill="#e05252" opacity="0.9"/>
<text x="240" y="15.5" font-size="6" fill="#fff" text-anchor="middle" font-weight="700" font-family="Inter,sans-serif">4</text>
<!-- Items with colored dots -->
<circle cx="22" cy="44" r="3.5" fill="#3d9e5a"/>
<text x="32" y="47" font-size="7.5" fill="#555" font-family="Inter,sans-serif">New: Vol II Ch. 14 — Fault Tolerance</text>
<circle cx="22" cy="62" r="3.5" fill="#4a90c4"/>
<text x="32" y="65" font-size="7.5" fill="#555" font-family="Inter,sans-serif">Updated: TinyTorch Module 12</text>
<circle cx="22" cy="80" r="3.5" fill="#c87b2a"/>
<text x="32" y="83" font-size="7.5" fill="#555" font-family="Inter,sans-serif">Community: 500+ PRs merged</text>
<circle cx="22" cy="98" r="3.5" fill="#6a4da8"/>
<text x="32" y="101" font-size="7.5" fill="#555" font-family="Inter,sans-serif">Milestone: 23,000 GitHub stars</text>
<!-- Footer -->
<line x1="16" y1="114" x2="248" y2="114" stroke="#e2e8f0" stroke-width="0.8"/>
<text x="132" y="128" font-size="7" fill="#94a3b8" text-anchor="middle" font-weight="600" font-family="Inter,sans-serif">Join 12,000+ subscribers</text>
</svg>
</div>
</a>
</div>
<div class="mls-scroll-indicator mls-scroll-2" role="button" tabindex="0" aria-label="Scroll to support section">
<span>Support the Mission</span>
<div class="mls-scroll-arrow">&darr;</div>
</div>
</section>
<!-- ═══ Snap 3: Impact & Support ═══ -->
<section class="mls-section mls-section-impact" id="support">
<div class="mls-impact-top">
<p class="mls-impact-eyebrow">OUR MISSION</p>
<p class="mls-impact-headline">AI education should be<br/>free and open to everyone.</p>
<p class="mls-impact-mission">Everyone calls AI the new electricity — but electricity is useless without engineers who can build the grid. For AI to be efficient, reliable, and safe, the world needs engineers who understand how to build it.</p>
<p class="mls-impact-mission">That knowledge should be accessible to anyone willing to learn. This curriculum is our commitment to making it so.</p>
</div>
<div class="mls-reader-map">
<div class="mls-looker-wrap">
<iframe
src="https://lookerstudio.google.com/embed/reporting/e7192975-a8a0-453d-b6fe-1580ac054dbf/page/0pNbE"
title="Global readership map — 243,000+ readers across 180+ countries"
allowfullscreen="allowfullscreen"
loading="lazy"
sandbox="allow-storage-access-by-user-activation allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox">
</iframe>
</div>
<p class="mls-map-caption">Live readership — 180+ countries</p>
</div>
<div class="mls-impact-bottom">
<p class="mls-impact-stats-line"><span class="gh-star-count">23,000+</span> stars &middot; 243,000+ readers &middot; 180+ countries</p>
<div class="mls-goal-block">
<p class="mls-impact-goal">Our goal: <strong>1,000,000 AI engineers by 2030</strong></p>
<p class="mls-impact-goal-sub">Next milestone: 100,000 ★ — we're at <span class="gh-star-count">23,000+</span>.<br/>Every star helps others discover this resource.</p>
</div>
<div class="mls-star-row">
<a href="https://github.com/harvard-edge/cs249r_book" target="_blank" rel="noopener" class="mls-footer-btn mls-btn-star">
<svg width="16" height="16" viewBox="0 0 16 16" fill="#e3b341" aria-hidden="true" focusable="false"><path d="M8 .25a.75.75 0 01.673.418l1.882 3.815 4.21.612a.75.75 0 01.416 1.279l-3.046 2.97.719 4.192a.75.75 0 01-1.088.791L8 12.347l-3.766 1.98a.75.75 0 01-1.088-.79l.72-4.194L.818 6.374a.75.75 0 01.416-1.28l4.21-.611L7.327.668A.75.75 0 018 .25z"/></svg>
Star on GitHub
</a>
</div>
<p class="mls-impact-sponsors"><a href="community/partners.html">Meet our sponsors &amp; partners &rarr;</a></p>
</div>
</section>
</div>
<script src="neural-bg.js"></script>
<script>
// Clickable scroll indicators
document.querySelectorAll('.mls-scroll-indicator').forEach(ind => {
const target = ind.classList.contains('mls-scroll-2') ? '#support' : '#curriculum';
ind.addEventListener('click', () => {
document.querySelector(target)?.scrollIntoView({ behavior: 'smooth' });
});
ind.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
document.querySelector(target)?.scrollIntoView({ behavior: 'smooth' });
}
});
});
// Fetch live GitHub star count — update all instances
fetch('https://api.github.com/repos/harvard-edge/cs249r_book')
.then(r => r.json())
.then(d => {
if (d.stargazers_count) {
const fmt = d.stargazers_count.toLocaleString();
document.querySelectorAll('.gh-star-count').forEach(el => {
el.textContent = fmt;
});
}
})
.catch(() => {});
</script>
```
:::