Skip to content

Commit 5a5c195

Browse files
committed
Merge PR #1957: Finalize Volume I layout for full PDF draft
# Conflicts: # book/quarto/contents/vol1/ml_ops/ml_ops.qmd
2 parents aba8eb1 + c926e57 commit 5a5c195

23 files changed

Lines changed: 492 additions & 404 deletions

File tree

book/quarto/contents/vol1/backmatter/appendix_dam.qmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ To move beyond qualitative guessing, the efficiency ratios in @tbl-dam-scorecard
228228

229229
```{=latex}
230230
\begingroup
231-
\renewcommand{\arraystretch}{2.5}
231+
\renewcommand{\arraystretch}{3}
232232
```
233233

234234
| **Axis** | **Metric** | **Definition** | **Failing Grade** | **Passing Grade** |

book/quarto/contents/vol1/backmatter/glossary/glossary.qmd

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@ This glossary defines key terms used throughout this book and gathers them as a
1010
```{=latex}
1111
\scriptsize\sloppy
1212
\setlength{\parskip}{1pt plus 0.5pt}
13+
\setlist[description]{
14+
style=unboxed,
15+
leftmargin=1.4em,
16+
itemindent=-1.4em,
17+
labelindent=0pt,
18+
labelsep=0.5em,
19+
font=\normalfont\bfseries,
20+
itemsep=2pt,
21+
parsep=0pt,
22+
topsep=0pt
23+
}
1324
\begin{multicols}{3}
1425
```
1526

@@ -841,7 +852,7 @@ This glossary defines key terms used throughout this book and gathers them as a
841852
**Kolmogorov-Smirnov test (K-S test)**
842853
: A nonparametric test that measures the maximum distance between two cumulative distributions, often used to compare feature distributions for drift.
843854

844-
**Kullback-Leibler divergence (KL divergence)**
855+
Kullback-Leibler divergence (KL divergence)
845856
: An asymmetric information-theoretic measure of how one probability distribution differs from another, used in monitoring and drift analysis.
846857

847858
**KV cache**

book/quarto/contents/vol1/benchmarking/benchmarking.qmd

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2264,6 +2264,11 @@ With perfect scaling, `{python} ScalingEfficiencyCalc.n_gpus_str` would complete
22642264

22652265
**Step 3**: Account for the efficiency loss. @Tbl-benchmarking-scaling-efficiency-loss decomposes the "missing" `{python} ScalingEfficiencyCalc.loss_str` into measurable overhead categories—gradient synchronization, memory copy, load imbalance, and batch-size effects—each measurable through a distinct profiling signal.
22662266

2267+
```{=latex}
2268+
\begingroup
2269+
\renewcommand{\arraystretch}{1.3}
2270+
```
2271+
22672272
| **Source** | **Example Contribution** | **Measurement** |
22682273
|:-----------------------------|:------------------------:|:------------------------------------|
22692274
| **Gradient synchronization** | 10-15% | AllReduce time per step |
@@ -2273,6 +2278,10 @@ With perfect scaling, `{python} ScalingEfficiencyCalc.n_gpus_str` would complete
22732278

22742279
: **Scaling Efficiency Loss Sources**: Illustrative decomposition of the missing efficiency budget into measurable overhead categories and the corresponding measurement signal used to attribute each loss. Actual percentages depend on model, interconnect, storage, batch schedule, and framework implementation. {#tbl-benchmarking-scaling-efficiency-loss}
22752280

2281+
```{=latex}
2282+
\endgroup
2283+
```
2284+
22762285
**Step 4**: The systems insight.
22772286
<!-- lego-ok-block: typical strong-scaling efficiency ranges at different GPU counts -->
22782287
Scaling efficiency decreases as $N_{\text{GPU}}$ grows because communication overhead scales with GPU count while per-GPU compute shrinks. In this worked example, eight GPUs reach 75 percent efficiency; at larger scales, the same arithmetic makes clear why sophisticated communication and input-pipeline optimization become necessary.
@@ -2699,15 +2708,15 @@ These metrics interact through unavoidable trade-offs. Optimizing for high throu
26992708

27002709
Deployment scenario determines the priority order among those metrics. The operational constraints and success criteria vary dramatically across contexts, so metric priorities help engineers focus benchmarking effort and interpret results within the right decision framework. @Tbl-metric-priorities illustrates how performance priorities shift across five major deployment contexts, revealing the systematic relationship between operational constraints and optimization targets.
27012710

2702-
| **Deployment Context** | **Primary Priority** | **Secondary Priority** | **Tertiary Priority** | **Key Design Constraint** |
2703-
|:---------------------------|:----------------------|:-----------------------|:----------------------|:--------------------------------------------------|
2704-
| **Real-Time Applications** | Latency (p95 < 50 ms) | Reliability (99.9%) | Memory Footprint | User experience demands immediate response |
2705-
| **Cloud-Scale Services** | Throughput (QPS) | Cost Efficiency | Average Latency | Business viability requires massive scale |
2706-
| **Edge/Mobile Devices** | Power Consumption | Memory Footprint | Latency | Battery life and resource limits dominate |
2707-
| **Training Workloads** | Training Time | GPU Utilization | Memory Efficiency | Research velocity enables faster experimentation |
2708-
| **Scientific/Medical** | Accuracy | Reliability | Explainability | Correctness cannot be compromised for performance |
2711+
| **Deployment Context** | **Primary Priority** | **Secondary Priority** | **Tertiary Priority** | **Key Design Constraint** |
2712+
|:---------------------------|:---------------------|:-----------------------|:----------------------|:--------------------------------------------------|
2713+
| **Real-Time Applications** | Latency (p95 < 50 ms)| Reliability (99.9%) | Memory Footprint | User experience demands immediate response |
2714+
| **Cloud-Scale Services** | Throughput (QPS) | Cost Efficiency | Average Latency | Business viability requires massive scale |
2715+
| **Edge/Mobile Devices** | Power Consumption | Memory Footprint | Latency | Battery life and resource limits dominate |
2716+
| **Training Workloads** | Training Time | GPU Utilization | Memory Efficiency | Research velocity enables faster experimentation |
2717+
| **Scientific/Medical** | Accuracy | Reliability | Explainability | Correctness cannot be compromised for performance |
27092718

2710-
: **Performance Metric Priorities by Deployment Context**: Different operational environments demand distinct optimization focuses, reflecting varying constraints and success criteria. These priorities guide both benchmark selection and result interpretation. {#tbl-metric-priorities tbl-colwidths="[18,16,20,18,28]"}
2719+
: **Performance Metric Priorities by Deployment Context**: Different operational environments demand distinct optimization focuses, reflecting varying constraints and success criteria. These priorities guide both benchmark selection and result interpretation. {#tbl-metric-priorities tbl-colwidths="[18,19,18,17,28]"}
27112720

27122721
The key insight from @tbl-metric-priorities is that the same metric can be primary in one context and irrelevant in another. Latency ranks first for real-time applications (autonomous vehicles must process sensor data within strict timing deadlines) but tertiary for cloud services (which accept higher latency in exchange for cost efficiency per query). A smartphone AI assistant that improves throughput by 50 percent but increases power consumption by 30 percent represents a net regression since battery life directly impacts user satisfaction. Medical diagnostic systems prioritize accuracy as nonnegotiable—achieving 99.2 percent accuracy at 10 ms latency provides superior value compared to 98.8 percent at 5 ms. This context-dependence means that a 2$\times$ throughput improvement represents substantial value for cloud deployments but minimal benefit for battery-powered edge devices, where 20 percent power reduction delivers superior operational impact.
27132722

book/quarto/contents/vol1/conclusion/conclusion.qmd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ The Lighthouse Models now become a constraint map for reasoning about ML systems
9595

9696
The five Lighthouse Models\index{Lighthouse Model!bottleneck probe} introduced in @sec-introduction-iron-law-ml-systems-c32a made this constraint propagation concrete, serving as systems detectives throughout the book. Each revealed how different workloads expose different bottlenecks.
9797

98+
```{=latex}
99+
\newpage
100+
```
98101
The five Lighthouse workloads expose distinct constraint regimes:
99102

100103
- **ResNet-50**: Batch size can turn image inference from a memory-bound path into compute-bound throughput.

book/quarto/contents/vol1/data_engineering/data_engineering.qmd

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ Text2/.style={align=left,anchor=north west,font=\footnotesize\usefont{T1}{phv}{m
422422
\fill[black] (P\i) circle (2pt);
423423
}
424424
425-
\draw[LineD,Red](P0)to[out=60,in=120](P6);
425+
\draw[LineD,Red,overlay](P0)to[out=60,in=120](P6);
426426
\draw[LineD,Red](P0)to[out=60,in=125](P5);
427427
\draw[LineD,Blue](P1)to[out=60,in=120](P6);
428428
\draw[LineD,Red](P1)to[out=50,in=125](P6);
@@ -1428,14 +1428,14 @@ pics/globe/.style = {
14281428
%%%%%%%%%%%%%%%%%%
14291429
\node[Box2,below=1.85 of B1](B2){};
14301430
\draw[mygreen, line width=2.75pt](B2.south west)--coordinate[pos=0.5](SR2)(B2.south east);
1431-
\node[Box2,right= of B2](B3){};
1431+
\node[Box2,right= 1.4 of B2](B3){};
14321432
\draw[mygreen, line width=2.75pt](B3.south west)--coordinate[pos=0.5](SR3)(B3.south east);
1433-
\node[Box2,right= of B3](B4){};
1433+
\node[Box2,right=1.4 of B3](B4){};
14341434
\draw[mygreen, line width=2.75pt](B4.south west)--coordinate[pos=0.5](SR4)(B4.south east);
14351435
%
1436-
\node[Box2,left= of B2](B5){};
1436+
\node[Box2,left=1.4 of B2](B5){};
14371437
\draw[mygreen, line width=2.75pt](B5.south west)--coordinate[pos=0.5](SR5)(B5.south east);
1438-
\node[Box2,left= of B5](B6){};
1438+
\node[Box2,left=1.4 of B5](B6){};
14391439
\draw[mygreen, line width=2.75pt](B6.south west)--coordinate[pos=0.5](SR6)(B6.south east);
14401440
14411441
\foreach \i [count=\k from 2] in {C,D,E,B,A}{
@@ -1562,49 +1562,6 @@ Just as systems engineers memorize latency numbers, ML engineers should internal
15621562

15631563
@Tbl-data-engineering-time-constants extends the picture with characteristic durations for labeling, training, and serving operations.
15641564

1565-
```{python}
1566-
#| echo: false
1567-
#| label: data-engineering-time-constants-calc
1568-
# ┌─────────────────────────────────────────────────────────────────────────────
1569-
# │ DATA ENGINEERING TIME CONSTANTS SPAN
1570-
# ├─────────────────────────────────────────────────────────────────────────────
1571-
# │ Context: @tbl-data-engineering-time-constants caption
1572-
# │
1573-
# │ Goal: Compute the order-of-magnitude span shown in the table.
1574-
# │ Show: Labeling weeks vs. feature-lookup milliseconds spans about 9 orders.
1575-
# │ How: Compare the slowest listed labeling bound with the fastest lookup bound.
1576-
# │
1577-
# └─────────────────────────────────────────────────────────────────────────────
1578-
from math import log10
1579-
from mlsysim.fmt import fmt_int, fmt, fmt_count, check
1580-
1581-
class DataEngineeringTimeConstants:
1582-
"""Order-of-magnitude span for data-engineering operation durations."""
1583-
1584-
# ┌── 1. LOAD (Constants) ──────────────────────────────────────────────
1585-
fastest_lookup_s = 0.001
1586-
slowest_labeling_weeks = 4
1587-
seconds_per_week = 7 * 24 * 60 * 60
1588-
1589-
# ┌── 2. EXECUTE (The Compute) ────────────────────────────────────────
1590-
slowest_labeling_s = slowest_labeling_weeks * seconds_per_week
1591-
span_ratio = slowest_labeling_s / fastest_lookup_s
1592-
span_orders = log10(span_ratio)
1593-
1594-
# ┌── 3. GUARD (Invariants) ───────────────────────────────────────────
1595-
check(span_orders > 9, f"Time constants should span more than 9 orders, got {span_orders:.2f}.")
1596-
1597-
# ┌── 4. OUTPUT (Formatting) ──────────────────────────────────────────
1598-
span_orders_str = fmt_int(span_orders, commas=False)
1599-
```
1600-
1601-
| **Operation** | **Duration** | **Bottleneck** |
1602-
|:-----------------------------------|:------------:|:------------------------------------|
1603-
| **Label 1M images (crowdsourced)** | 2–4 weeks | Annotation throughput |
1604-
| **Train ResNet-50 on ImageNet** | 4–6 hours | Compute (8$\times$ A100, optimized) |
1605-
| **Feature store lookup** | 1–10 ms | Network + cache |
1606-
1607-
: **Data Engineering Time Constants**: Characteristic durations for labeling, training, and serving operations span about `{python} DataEngineeringTimeConstants.span_orders_str` orders of magnitude. Human labeling sets the wall-clock floor for new datasets, making it the dominant scheduling constraint in production ML systems. {#tbl-data-engineering-time-constants tbl-colwidths="[40,34,36]"}
16081565

16091566
```{python}
16101567
#| echo: false
@@ -1660,6 +1617,51 @@ class LabelingComputeRatio:
16601617

16611618
The contrast matters: weeks for human labeling, hours for GPU training, milliseconds for serving. Labeling is the bottleneck. It often costs hundreds to more than a thousand times more than a single optimized training run: a `{python} LabelingComputeRatio.labeling_budget_str` labeling budget compares with `{python} LabelingComputeRatio.train_cost_low_str`--`{python} LabelingComputeRatio.train_cost_high_str` for one 8$\times$ A100 ResNet-50 run, a `{python} LabelingComputeRatio.ratio_low_mult_str`--`{python} LabelingComputeRatio.ratio_high_mult_str` ratio. Within that labeling spend, the effort distribution itself is skewed: `{python} LabelingComputeRatio.effort_majority_pct_str` of the work goes to `{python} LabelingComputeRatio.effort_minority_pct_str` of features—the long tail of edge cases, rare categories, and quality exceptions.
16621619

1620+
```{python}
1621+
#| echo: false
1622+
#| label: data-engineering-time-constants-calc
1623+
# ┌─────────────────────────────────────────────────────────────────────────────
1624+
# │ DATA ENGINEERING TIME CONSTANTS SPAN
1625+
# ├─────────────────────────────────────────────────────────────────────────────
1626+
# │ Context: @tbl-data-engineering-time-constants caption
1627+
# │
1628+
# │ Goal: Compute the order-of-magnitude span shown in the table.
1629+
# │ Show: Labeling weeks vs. feature-lookup milliseconds spans about 9 orders.
1630+
# │ How: Compare the slowest listed labeling bound with the fastest lookup bound.
1631+
# │
1632+
# └─────────────────────────────────────────────────────────────────────────────
1633+
from math import log10
1634+
from mlsysim.fmt import fmt_int, fmt, fmt_count, check
1635+
1636+
class DataEngineeringTimeConstants:
1637+
"""Order-of-magnitude span for data-engineering operation durations."""
1638+
1639+
# ┌── 1. LOAD (Constants) ──────────────────────────────────────────────
1640+
fastest_lookup_s = 0.001
1641+
slowest_labeling_weeks = 4
1642+
seconds_per_week = 7 * 24 * 60 * 60
1643+
1644+
# ┌── 2. EXECUTE (The Compute) ────────────────────────────────────────
1645+
slowest_labeling_s = slowest_labeling_weeks * seconds_per_week
1646+
span_ratio = slowest_labeling_s / fastest_lookup_s
1647+
span_orders = log10(span_ratio)
1648+
1649+
# ┌── 3. GUARD (Invariants) ───────────────────────────────────────────
1650+
check(span_orders > 9, f"Time constants should span more than 9 orders, got {span_orders:.2f}.")
1651+
1652+
# ┌── 4. OUTPUT (Formatting) ──────────────────────────────────────────
1653+
span_orders_str = fmt_int(span_orders, commas=False)
1654+
```
1655+
1656+
| **Operation** | **Duration** | **Bottleneck** |
1657+
|:-----------------------------------|:------------:|:------------------------------------|
1658+
| **Label 1M images (crowdsourced)** | 2–4 weeks | Annotation throughput |
1659+
| **Train ResNet-50 on ImageNet** | 4–6 hours | Compute (8$\times$ A100, optimized) |
1660+
| **Feature store lookup** | 1–10 ms | Network + cache |
1661+
1662+
: **Data Engineering Time Constants**: Characteristic durations for labeling, training, and serving operations span about `{python} DataEngineeringTimeConstants.span_orders_str` orders of magnitude. Human labeling sets the wall-clock floor for new datasets, making it the dominant scheduling constraint in production ML systems. {#tbl-data-engineering-time-constants tbl-colwidths="[40,34,36]"}
1663+
1664+
16631665
All cost figures reflect approximate 2024 cloud provider rates and are intended to convey relative magnitudes rather than exact pricing.[^fn-pricing-cost-ratios] The consistent pattern across these numbers is that human labor (labeling, annotation, expert review) dominates hardware and storage costs by one to three orders of magnitude. A team that optimizes its labeling pipeline before scaling compute or storage addresses the largest cost term first.
16641666

16651667
```{python}

0 commit comments

Comments
 (0)