mirror of
https://github.com/harvard-edge/cs249r_book.git
synced 2026-05-07 10:08:50 -05:00
The same path-prefix bug that broke Lander on dev preview affected the other
13 games too. Fixing all of them in one batch so the entire catalog works
on /cs249r_book_dev/, mlsysbook.ai/, and localhost equally.
Pattern applied:
.qmd include-in-header script:
import "/assets/games/X.mjs" → import "../assets/games/X.mjs"
.mjs ES imports:
from "/assets/games/runtime.mjs" → from "./runtime.mjs"
from "/assets/games/vendor/pixi.min.mjs" → from "./vendor/pixi.min.mjs"
Files touched (10 .mjs + 13 .qmd):
.mjs: allreduce, batch, cluster, kvcache, moe, oom, pipeline, prune,
quantization, topology
.qmd: allreduce, batch, checkpoint, cluster, kvcache, loader, moe, oom,
pipeline, prune, quantization, roofline, topology
(checkpoint, loader, roofline .mjs already used 'import * as runtime from
./runtime.mjs' — only their qmd files needed updating)
Verification: all 14 games rendered locally (quarto render games/), served
via python3 -m http.server, swept with Playwright headless Chromium.
Result: 14/14 pass — canvas mounted, MLSP runtime ready, game registered,
no JS errors, no 4xx network requests. Visual screenshots confirm each
game's HUD/title/content paints correctly.
78 lines
3.1 KiB
Plaintext
78 lines
3.1 KiB
Plaintext
---
|
|
title: "Data Loader Dash"
|
|
subtitle: "The CPU preparing data before the GPU starves."
|
|
description: "A browser mini-game from MLSysBook Playground. Type the letters to prepare data blocks before they reach the GPU."
|
|
page-layout: article
|
|
format:
|
|
html:
|
|
include-in-header:
|
|
- text: |
|
|
<link rel="stylesheet" href="/assets/games/common.css">
|
|
<script type="module">
|
|
import "../assets/games/runtime.mjs";
|
|
import "../assets/games/loader.mjs";
|
|
</script>
|
|
---
|
|
|
|
```{=html}
|
|
<div class="mlsp-game-container" role="region" aria-label="Data Loader Dash mini-game">
|
|
<canvas id="mlsp-canvas" class="mlsp-game-canvas" width="680" height="460"></canvas>
|
|
<div class="mlsp-game-hud">
|
|
<span class="mlsp-score">health <span id="mlsp-health">100</span> · score <span id="mlsp-score">0</span></span>
|
|
<span>type <kbd>J</kbd> <kbd>C</kbd> <kbd>A</kbd> <kbd>T</kbd> in the zone · keep the GPU fed · <kbd>R</kbd> retry</span>
|
|
<button type="button" class="mlsp-fullscreen-btn" onclick="this.closest('.mlsp-game-container').requestFullscreen()" title="Full Screen" aria-label="Full Screen">⛶</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="mlsp-aha-slot"></div>
|
|
|
|
<script>
|
|
(function bootLoader(){
|
|
function tryBoot() {
|
|
if (!window.MLSP || !MLSP.games || !MLSP.games.loader) return setTimeout(tryBoot, 30);
|
|
var canvas = document.getElementById("mlsp-canvas");
|
|
var $score = document.getElementById("mlsp-score");
|
|
var $health = document.getElementById("mlsp-health");
|
|
var ahaSlot = document.getElementById("mlsp-aha-slot");
|
|
var pendingResult = null;
|
|
var resolvedApi = null;
|
|
|
|
window.addEventListener('keydown', function(e) {
|
|
if (e.key.toLowerCase() === 'r') window.location.reload();
|
|
});
|
|
|
|
Promise.resolve(MLSP.games.loader(canvas, {
|
|
onScoreChange: function(s) { $score.textContent = s.score; $health.textContent = s.health; },
|
|
onGameOver: function(result) {
|
|
if (resolvedApi) attachAha(resolvedApi, result);
|
|
else pendingResult = result;
|
|
},
|
|
onRetry: function() { window.location.reload(); }
|
|
})).then(function(api) {
|
|
resolvedApi = api;
|
|
if (pendingResult) attachAha(api, pendingResult);
|
|
});
|
|
|
|
function attachAha(api, result) {
|
|
MLSP.showAhaCard(ahaSlot, api.ahaLabel, api.ahaText, api.ahaLink);
|
|
}
|
|
}
|
|
tryBoot();
|
|
})();
|
|
</script>
|
|
```
|
|
|
|
## How to play
|
|
|
|
1. Watch the conveyor. A block only counts if it is inside the processing zone.
|
|
2. Type the matching key: <kbd>J</kbd>, <kbd>C</kbd>, <kbd>A</kbd>, or <kbd>T</kbd>. Correct hits turn raw samples into tensors.
|
|
3. Keep the GPU fed for as long as possible. Missed blocks damage health; slow processing lets hunger drain.
|
|
|
|
## The Systems Concept
|
|
|
|
In data pipelines, the CPU often needs to load, decode, augment, batch, and transfer examples before the GPU can train. If preprocessing throughput falls below GPU consumption, expensive accelerators sit idle. Efficient data loading is not background plumbing; it is part of the training system's critical path.
|
|
|
|
---
|
|
|
|
*Part of [MLSysBook Playground](/games/). Found a bug? [Report an issue](https://github.com/harvard-edge/cs249r_book/issues/new?labels=bug&title=Bug+in+Game).*
|