mirror of
https://github.com/MLSysBook/TinyTorch.git
synced 2026-08-01 02:58:18 -05:00
Add normalized scoring and MLPerf principles to Module 19
Enhancements to benchmarking module: - Added calculate_normalized_scores() for fair hardware comparison - Implemented speedup, compression ratio, accuracy delta metrics - Added MLPerf principles section to educational content - Updated module to support competition fairness These changes enable Module 20 competition to work across different hardware.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "0f6c62ff",
|
||||
"id": "e9ff31aa",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -13,7 +13,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "40158b0d",
|
||||
"id": "d49b6d28",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\""
|
||||
},
|
||||
@@ -54,7 +54,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "7bb7b96d",
|
||||
"id": "1dd61735",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\""
|
||||
},
|
||||
@@ -83,7 +83,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "39c18e66",
|
||||
"id": "cdb58292",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\""
|
||||
},
|
||||
@@ -119,7 +119,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "ec7d8e69",
|
||||
"id": "a41ba608",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\""
|
||||
},
|
||||
@@ -172,7 +172,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "0b3993a6",
|
||||
"id": "3698099e",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -197,7 +197,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "c14f714c",
|
||||
"id": "1ba1d3dc",
|
||||
"metadata": {
|
||||
"lines_to_next_cell": 1
|
||||
},
|
||||
@@ -222,7 +222,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "9054e08f",
|
||||
"id": "e4bd5a37",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\""
|
||||
},
|
||||
@@ -251,7 +251,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "dc131487",
|
||||
"id": "17a008af",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\"",
|
||||
"lines_to_next_cell": 1
|
||||
@@ -291,7 +291,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "ad20a4c8",
|
||||
"id": "58b069fb",
|
||||
"metadata": {
|
||||
"nbgrader": {
|
||||
"grade": false,
|
||||
@@ -400,7 +400,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "c0df7489",
|
||||
"id": "8205c609",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\"",
|
||||
"lines_to_next_cell": 1
|
||||
@@ -453,7 +453,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "38491cfa",
|
||||
"id": "ec6dd3bb",
|
||||
"metadata": {
|
||||
"nbgrader": {
|
||||
"grade": false,
|
||||
@@ -533,7 +533,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "149f5f9a",
|
||||
"id": "e369a7a0",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\"",
|
||||
"lines_to_next_cell": 1
|
||||
@@ -601,7 +601,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "d53f0474",
|
||||
"id": "e9daff37",
|
||||
"metadata": {
|
||||
"nbgrader": {
|
||||
"grade": false,
|
||||
@@ -876,7 +876,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "2ea120cb",
|
||||
"id": "1530cb11",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\"",
|
||||
"lines_to_next_cell": 1
|
||||
@@ -940,7 +940,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "f9cfacc6",
|
||||
"id": "49bc9ee6",
|
||||
"metadata": {
|
||||
"nbgrader": {
|
||||
"grade": false,
|
||||
@@ -1317,7 +1317,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "4239143f",
|
||||
"id": "8f1ca772",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\"",
|
||||
"lines_to_next_cell": 1
|
||||
@@ -1394,7 +1394,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "93f6691b",
|
||||
"id": "c48dd641",
|
||||
"metadata": {
|
||||
"nbgrader": {
|
||||
"grade": false,
|
||||
@@ -1768,7 +1768,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "05bec50f",
|
||||
"id": "bce5e722",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\""
|
||||
},
|
||||
@@ -1800,7 +1800,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "8a879de8",
|
||||
"id": "fceb0478",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\"",
|
||||
"lines_to_next_cell": 1
|
||||
@@ -1853,7 +1853,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "e1fe12aa",
|
||||
"id": "e0e9d140",
|
||||
"metadata": {
|
||||
"nbgrader": {
|
||||
"grade": false,
|
||||
@@ -2094,7 +2094,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "9cc1cdcb",
|
||||
"id": "026dcc7d",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\""
|
||||
},
|
||||
@@ -2184,12 +2184,258 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "34d08319",
|
||||
"id": "20aa0b56",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\""
|
||||
},
|
||||
"source": [
|
||||
"## 4.5 Combination Strategies - Preparing for TorchPerf Olympics\n",
|
||||
"## 4.5 Normalized Metrics - Fair Comparison Across Different Hardware\n",
|
||||
"\n",
|
||||
"### The Hardware Problem\n",
|
||||
"\n",
|
||||
"Imagine two students submit their optimizations:\n",
|
||||
"- **Alice** (M3 Mac, 16GB RAM): \"My model runs at 50ms latency!\"\n",
|
||||
"- **Bob** (2015 laptop, 4GB RAM): \"My model runs at 200ms latency!\"\n",
|
||||
"\n",
|
||||
"Who optimized better? **You can't tell from raw numbers!**\n",
|
||||
"\n",
|
||||
"Alice's hardware is 4x faster. If Bob achieved 200ms on old hardware, he might have optimized MORE aggressively than Alice. Raw metrics are unfair.\n",
|
||||
"\n",
|
||||
"### The Solution: Relative Improvement Metrics\n",
|
||||
"\n",
|
||||
"Instead of absolute performance, measure **relative improvement** from YOUR baseline:\n",
|
||||
"\n",
|
||||
"```\n",
|
||||
"Speedup = Baseline Latency / Optimized Latency\n",
|
||||
"Compression Ratio = Baseline Memory / Optimized Memory \n",
|
||||
"Accuracy Delta = Optimized Accuracy - Baseline Accuracy\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"**Example:**\n",
|
||||
"- Alice: 100ms → 50ms = **2.0x speedup** ✓\n",
|
||||
"- Bob: 400ms → 200ms = **2.0x speedup** ✓\n",
|
||||
"\n",
|
||||
"Now they're fairly compared! Both achieved 2x speedup on their hardware.\n",
|
||||
"\n",
|
||||
"### Key Normalized Metrics for TorchPerf Olympics\n",
|
||||
"\n",
|
||||
"**1. Speedup (for Latency Sprint)**\n",
|
||||
"```python\n",
|
||||
"speedup = baseline_latency / optimized_latency\n",
|
||||
"# Higher is better: 2.5x means 2.5 times faster\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"**2. Compression Ratio (for Memory Challenge)**\n",
|
||||
"```python\n",
|
||||
"compression_ratio = baseline_memory / optimized_memory\n",
|
||||
"# Higher is better: 4.0x means 4 times smaller\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"**3. Accuracy Preservation (for All Events)**\n",
|
||||
"```python\n",
|
||||
"accuracy_delta = optimized_accuracy - baseline_accuracy\n",
|
||||
"# Closer to 0 is better: -0.02 means 2% accuracy drop\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"**4. Efficiency Score (for All-Around)**\n",
|
||||
"```python\n",
|
||||
"efficiency = (speedup * compression_ratio) / max(1.0, abs(accuracy_delta))\n",
|
||||
"# Balances all metrics\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"### Why This Matters for Your Competition\n",
|
||||
"\n",
|
||||
"**Without normalization:**\n",
|
||||
"- Newest hardware wins unfairly\n",
|
||||
"- Focus shifts to \"who has the best laptop\"\n",
|
||||
"- Optimization skill doesn't matter\n",
|
||||
"\n",
|
||||
"**With normalization:**\n",
|
||||
"- Everyone competes on **optimization skill**\n",
|
||||
"- Hardware differences are eliminated\n",
|
||||
"- Focus is on relative improvement\n",
|
||||
"\n",
|
||||
"**Real MLPerf Example:**\n",
|
||||
"```\n",
|
||||
"NVIDIA A100 submission: 2.1ms (absolute) → 3.5x speedup (relative)\n",
|
||||
"Google TPU submission: 1.8ms (absolute) → 4.2x speedup (relative)\n",
|
||||
"\n",
|
||||
"Winner: Google (better speedup despite slower absolute time)\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"### Implementing Normalized Scoring"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "6c051c23",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\"",
|
||||
"lines_to_next_cell": 1
|
||||
},
|
||||
"source": [
|
||||
"Let's implement a helper function to calculate normalized scores for the competition:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "75393e9b",
|
||||
"metadata": {
|
||||
"lines_to_next_cell": 1,
|
||||
"nbgrader": {
|
||||
"grade": false,
|
||||
"grade_id": "normalized-scoring",
|
||||
"locked": false
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#| export\n",
|
||||
"def calculate_normalized_scores(baseline_results: dict, \n",
|
||||
" optimized_results: dict) -> dict:\n",
|
||||
" \"\"\"\n",
|
||||
" Calculate normalized performance metrics for fair competition comparison.\n",
|
||||
" \n",
|
||||
" This function converts absolute measurements into relative improvements,\n",
|
||||
" enabling fair comparison across different hardware platforms.\n",
|
||||
" \n",
|
||||
" Args:\n",
|
||||
" baseline_results: Dict with keys: 'latency', 'memory', 'accuracy'\n",
|
||||
" optimized_results: Dict with same keys as baseline_results\n",
|
||||
" \n",
|
||||
" Returns:\n",
|
||||
" Dict with normalized metrics:\n",
|
||||
" - speedup: Relative latency improvement (higher is better)\n",
|
||||
" - compression_ratio: Relative memory reduction (higher is better)\n",
|
||||
" - accuracy_delta: Absolute accuracy change (closer to 0 is better)\n",
|
||||
" - efficiency_score: Combined metric balancing all factors\n",
|
||||
" \n",
|
||||
" Example:\n",
|
||||
" >>> baseline = {'latency': 100.0, 'memory': 12.0, 'accuracy': 0.89}\n",
|
||||
" >>> optimized = {'latency': 40.0, 'memory': 3.0, 'accuracy': 0.87}\n",
|
||||
" >>> scores = calculate_normalized_scores(baseline, optimized)\n",
|
||||
" >>> print(f\"Speedup: {scores['speedup']:.2f}x\")\n",
|
||||
" Speedup: 2.50x\n",
|
||||
" \"\"\"\n",
|
||||
" # Calculate speedup (higher is better)\n",
|
||||
" speedup = baseline_results['latency'] / optimized_results['latency']\n",
|
||||
" \n",
|
||||
" # Calculate compression ratio (higher is better)\n",
|
||||
" compression_ratio = baseline_results['memory'] / optimized_results['memory']\n",
|
||||
" \n",
|
||||
" # Calculate accuracy delta (closer to 0 is better, negative means degradation)\n",
|
||||
" accuracy_delta = optimized_results['accuracy'] - baseline_results['accuracy']\n",
|
||||
" \n",
|
||||
" # Calculate efficiency score (combined metric)\n",
|
||||
" # Penalize accuracy loss: the more accuracy you lose, the lower your score\n",
|
||||
" accuracy_penalty = max(1.0, 1.0 - accuracy_delta) if accuracy_delta < 0 else 1.0\n",
|
||||
" efficiency_score = (speedup * compression_ratio) / accuracy_penalty\n",
|
||||
" \n",
|
||||
" return {\n",
|
||||
" 'speedup': speedup,\n",
|
||||
" 'compression_ratio': compression_ratio,\n",
|
||||
" 'accuracy_delta': accuracy_delta,\n",
|
||||
" 'efficiency_score': efficiency_score,\n",
|
||||
" 'baseline': baseline_results.copy(),\n",
|
||||
" 'optimized': optimized_results.copy()\n",
|
||||
" }"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "16a7dbfe",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\"",
|
||||
"lines_to_next_cell": 1
|
||||
},
|
||||
"source": [
|
||||
"### 🧪 Unit Test: Normalized Scoring\n",
|
||||
"\n",
|
||||
"**This is a unit test** - it validates that normalized scoring correctly calculates relative improvements."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "a76bb43c",
|
||||
"metadata": {
|
||||
"nbgrader": {
|
||||
"grade": true,
|
||||
"grade_id": "test-normalized-scoring",
|
||||
"locked": true,
|
||||
"points": 1
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def test_unit_normalized_scoring():\n",
|
||||
" \"\"\"Test normalized scoring calculation.\"\"\"\n",
|
||||
" print(\"🔬 Unit Test: Normalized Scoring Calculation...\")\n",
|
||||
" \n",
|
||||
" # Test Case 1: Standard optimization (speedup + compression)\n",
|
||||
" baseline = {'latency': 100.0, 'memory': 12.0, 'accuracy': 0.89}\n",
|
||||
" optimized = {'latency': 40.0, 'memory': 3.0, 'accuracy': 0.87}\n",
|
||||
" \n",
|
||||
" scores = calculate_normalized_scores(baseline, optimized)\n",
|
||||
" \n",
|
||||
" assert abs(scores['speedup'] - 2.5) < 0.01, \"Speedup calculation incorrect\"\n",
|
||||
" assert abs(scores['compression_ratio'] - 4.0) < 0.01, \"Compression ratio incorrect\"\n",
|
||||
" assert abs(scores['accuracy_delta'] - (-0.02)) < 0.001, \"Accuracy delta incorrect\"\n",
|
||||
" print(\" ✅ Standard optimization scoring works\")\n",
|
||||
" \n",
|
||||
" # Test Case 2: Extreme optimization (high speedup, accuracy loss)\n",
|
||||
" optimized_extreme = {'latency': 20.0, 'memory': 1.5, 'accuracy': 0.75}\n",
|
||||
" scores_extreme = calculate_normalized_scores(baseline, optimized_extreme)\n",
|
||||
" \n",
|
||||
" assert scores_extreme['speedup'] > 4.0, \"Extreme speedup not detected\"\n",
|
||||
" assert scores_extreme['accuracy_delta'] < -0.1, \"Large accuracy loss not detected\"\n",
|
||||
" print(\" ✅ Extreme optimization scoring works\")\n",
|
||||
" \n",
|
||||
" # Test Case 3: Conservative optimization (minimal changes)\n",
|
||||
" optimized_conservative = {'latency': 90.0, 'memory': 11.0, 'accuracy': 0.89}\n",
|
||||
" scores_conservative = calculate_normalized_scores(baseline, optimized_conservative)\n",
|
||||
" \n",
|
||||
" assert abs(scores_conservative['accuracy_delta']) < 0.01, \"Accuracy preservation not detected\"\n",
|
||||
" print(\" ✅ Conservative optimization scoring works\")\n",
|
||||
" \n",
|
||||
" # Test Case 4: Accuracy improvement (rare but possible)\n",
|
||||
" optimized_better = {'latency': 80.0, 'memory': 10.0, 'accuracy': 0.91}\n",
|
||||
" scores_better = calculate_normalized_scores(baseline, optimized_better)\n",
|
||||
" \n",
|
||||
" assert scores_better['accuracy_delta'] > 0, \"Accuracy improvement not detected\"\n",
|
||||
" print(\" ✅ Accuracy improvement scoring works\")\n",
|
||||
" \n",
|
||||
" print(\"📈 Progress: Normalized Scoring ✓\\n\")\n",
|
||||
"\n",
|
||||
"test_unit_normalized_scoring()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "c1199666",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\""
|
||||
},
|
||||
"source": [
|
||||
"### Key Takeaways\n",
|
||||
"\n",
|
||||
"1. **Always report relative improvements, not absolute numbers**\n",
|
||||
"2. **Speedup and compression ratio are the primary metrics**\n",
|
||||
"3. **Accuracy delta shows the optimization cost**\n",
|
||||
"4. **Efficiency score balances all factors for All-Around event**\n",
|
||||
"\n",
|
||||
"**In Module 20**, you'll use `calculate_normalized_scores()` to generate your competition submission!"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "3dabdb12",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\""
|
||||
},
|
||||
"source": [
|
||||
"## 4.6 Combination Strategies - Preparing for TorchPerf Olympics\n",
|
||||
"\n",
|
||||
"You've learned individual optimizations (M14-18). Now it's time to combine them strategically! The order and parameters matter significantly for final performance.\n",
|
||||
"\n",
|
||||
@@ -2281,7 +2527,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "bdb56ec9",
|
||||
"id": "4d21ac76",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\"",
|
||||
"lines_to_next_cell": 1
|
||||
@@ -2297,7 +2543,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "54dd1924",
|
||||
"id": "73f8dc31",
|
||||
"metadata": {
|
||||
"nbgrader": {
|
||||
"grade": true,
|
||||
@@ -2329,6 +2575,7 @@
|
||||
" test_unit_benchmark_suite()\n",
|
||||
" test_unit_tinymlperf()\n",
|
||||
" test_unit_optimization_comparison()\n",
|
||||
" test_unit_normalized_scoring()\n",
|
||||
"\n",
|
||||
" print(\"\\nRunning integration scenarios...\")\n",
|
||||
"\n",
|
||||
@@ -2467,7 +2714,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "a291734b",
|
||||
"id": "f526d238",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -2479,7 +2726,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "b7f4a27d",
|
||||
"id": "fea34d89",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\""
|
||||
},
|
||||
@@ -2527,7 +2774,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "db353c04",
|
||||
"id": "aadfb85c",
|
||||
"metadata": {
|
||||
"cell_marker": "\"\"\""
|
||||
},
|
||||
|
||||
@@ -2023,203 +2023,7 @@ TinyMLPerf is MLPerf for embedded/edge devices:
|
||||
|
||||
# %% [markdown]
|
||||
"""
|
||||
## 4.5 Normalized Metrics - Fair Comparison Across Different Hardware
|
||||
|
||||
### The Hardware Problem
|
||||
|
||||
Imagine two students submit their optimizations:
|
||||
- **Alice** (M3 Mac, 16GB RAM): "My model runs at 50ms latency!"
|
||||
- **Bob** (2015 laptop, 4GB RAM): "My model runs at 200ms latency!"
|
||||
|
||||
Who optimized better? **You can't tell from raw numbers!**
|
||||
|
||||
Alice's hardware is 4x faster. If Bob achieved 200ms on old hardware, he might have optimized MORE aggressively than Alice. Raw metrics are unfair.
|
||||
|
||||
### The Solution: Relative Improvement Metrics
|
||||
|
||||
Instead of absolute performance, measure **relative improvement** from YOUR baseline:
|
||||
|
||||
```
|
||||
Speedup = Baseline Latency / Optimized Latency
|
||||
Compression Ratio = Baseline Memory / Optimized Memory
|
||||
Accuracy Delta = Optimized Accuracy - Baseline Accuracy
|
||||
```
|
||||
|
||||
**Example:**
|
||||
- Alice: 100ms → 50ms = **2.0x speedup** ✓
|
||||
- Bob: 400ms → 200ms = **2.0x speedup** ✓
|
||||
|
||||
Now they're fairly compared! Both achieved 2x speedup on their hardware.
|
||||
|
||||
### Key Normalized Metrics for TorchPerf Olympics
|
||||
|
||||
**1. Speedup (for Latency Sprint)**
|
||||
```python
|
||||
speedup = baseline_latency / optimized_latency
|
||||
# Higher is better: 2.5x means 2.5 times faster
|
||||
```
|
||||
|
||||
**2. Compression Ratio (for Memory Challenge)**
|
||||
```python
|
||||
compression_ratio = baseline_memory / optimized_memory
|
||||
# Higher is better: 4.0x means 4 times smaller
|
||||
```
|
||||
|
||||
**3. Accuracy Preservation (for All Events)**
|
||||
```python
|
||||
accuracy_delta = optimized_accuracy - baseline_accuracy
|
||||
# Closer to 0 is better: -0.02 means 2% accuracy drop
|
||||
```
|
||||
|
||||
**4. Efficiency Score (for All-Around)**
|
||||
```python
|
||||
efficiency = (speedup * compression_ratio) / max(1.0, abs(accuracy_delta))
|
||||
# Balances all metrics
|
||||
```
|
||||
|
||||
### Why This Matters for Your Competition
|
||||
|
||||
**Without normalization:**
|
||||
- Newest hardware wins unfairly
|
||||
- Focus shifts to "who has the best laptop"
|
||||
- Optimization skill doesn't matter
|
||||
|
||||
**With normalization:**
|
||||
- Everyone competes on **optimization skill**
|
||||
- Hardware differences are eliminated
|
||||
- Focus is on relative improvement
|
||||
|
||||
**Real MLPerf Example:**
|
||||
```
|
||||
NVIDIA A100 submission: 2.1ms (absolute) → 3.5x speedup (relative)
|
||||
Google TPU submission: 1.8ms (absolute) → 4.2x speedup (relative)
|
||||
|
||||
Winner: Google (better speedup despite slower absolute time)
|
||||
```
|
||||
|
||||
### Implementing Normalized Scoring
|
||||
"""
|
||||
|
||||
# %% [markdown]
|
||||
"""
|
||||
Let's implement a helper function to calculate normalized scores for the competition:
|
||||
"""
|
||||
|
||||
# %% nbgrader={"grade": false, "grade_id": "normalized-scoring", "locked": false}
|
||||
#| export
|
||||
def calculate_normalized_scores(baseline_results: dict,
|
||||
optimized_results: dict) -> dict:
|
||||
"""
|
||||
Calculate normalized performance metrics for fair competition comparison.
|
||||
|
||||
This function converts absolute measurements into relative improvements,
|
||||
enabling fair comparison across different hardware platforms.
|
||||
|
||||
Args:
|
||||
baseline_results: Dict with keys: 'latency', 'memory', 'accuracy'
|
||||
optimized_results: Dict with same keys as baseline_results
|
||||
|
||||
Returns:
|
||||
Dict with normalized metrics:
|
||||
- speedup: Relative latency improvement (higher is better)
|
||||
- compression_ratio: Relative memory reduction (higher is better)
|
||||
- accuracy_delta: Absolute accuracy change (closer to 0 is better)
|
||||
- efficiency_score: Combined metric balancing all factors
|
||||
|
||||
Example:
|
||||
>>> baseline = {'latency': 100.0, 'memory': 12.0, 'accuracy': 0.89}
|
||||
>>> optimized = {'latency': 40.0, 'memory': 3.0, 'accuracy': 0.87}
|
||||
>>> scores = calculate_normalized_scores(baseline, optimized)
|
||||
>>> print(f"Speedup: {scores['speedup']:.2f}x")
|
||||
Speedup: 2.50x
|
||||
"""
|
||||
# Calculate speedup (higher is better)
|
||||
speedup = baseline_results['latency'] / optimized_results['latency']
|
||||
|
||||
# Calculate compression ratio (higher is better)
|
||||
compression_ratio = baseline_results['memory'] / optimized_results['memory']
|
||||
|
||||
# Calculate accuracy delta (closer to 0 is better, negative means degradation)
|
||||
accuracy_delta = optimized_results['accuracy'] - baseline_results['accuracy']
|
||||
|
||||
# Calculate efficiency score (combined metric)
|
||||
# Penalize accuracy loss: the more accuracy you lose, the lower your score
|
||||
accuracy_penalty = max(1.0, 1.0 - accuracy_delta) if accuracy_delta < 0 else 1.0
|
||||
efficiency_score = (speedup * compression_ratio) / accuracy_penalty
|
||||
|
||||
return {
|
||||
'speedup': speedup,
|
||||
'compression_ratio': compression_ratio,
|
||||
'accuracy_delta': accuracy_delta,
|
||||
'efficiency_score': efficiency_score,
|
||||
'baseline': baseline_results.copy(),
|
||||
'optimized': optimized_results.copy()
|
||||
}
|
||||
|
||||
# %% [markdown]
|
||||
"""
|
||||
### 🧪 Unit Test: Normalized Scoring
|
||||
|
||||
**This is a unit test** - it validates that normalized scoring correctly calculates relative improvements.
|
||||
"""
|
||||
|
||||
# %% nbgrader={"grade": true, "grade_id": "test-normalized-scoring", "locked": true, "points": 1}
|
||||
def test_unit_normalized_scoring():
|
||||
"""Test normalized scoring calculation."""
|
||||
print("🔬 Unit Test: Normalized Scoring Calculation...")
|
||||
|
||||
# Test Case 1: Standard optimization (speedup + compression)
|
||||
baseline = {'latency': 100.0, 'memory': 12.0, 'accuracy': 0.89}
|
||||
optimized = {'latency': 40.0, 'memory': 3.0, 'accuracy': 0.87}
|
||||
|
||||
scores = calculate_normalized_scores(baseline, optimized)
|
||||
|
||||
assert abs(scores['speedup'] - 2.5) < 0.01, "Speedup calculation incorrect"
|
||||
assert abs(scores['compression_ratio'] - 4.0) < 0.01, "Compression ratio incorrect"
|
||||
assert abs(scores['accuracy_delta'] - (-0.02)) < 0.001, "Accuracy delta incorrect"
|
||||
print(" ✅ Standard optimization scoring works")
|
||||
|
||||
# Test Case 2: Extreme optimization (high speedup, accuracy loss)
|
||||
optimized_extreme = {'latency': 20.0, 'memory': 1.5, 'accuracy': 0.75}
|
||||
scores_extreme = calculate_normalized_scores(baseline, optimized_extreme)
|
||||
|
||||
assert scores_extreme['speedup'] > 4.0, "Extreme speedup not detected"
|
||||
assert scores_extreme['accuracy_delta'] < -0.1, "Large accuracy loss not detected"
|
||||
print(" ✅ Extreme optimization scoring works")
|
||||
|
||||
# Test Case 3: Conservative optimization (minimal changes)
|
||||
optimized_conservative = {'latency': 90.0, 'memory': 11.0, 'accuracy': 0.89}
|
||||
scores_conservative = calculate_normalized_scores(baseline, optimized_conservative)
|
||||
|
||||
assert abs(scores_conservative['accuracy_delta']) < 0.01, "Accuracy preservation not detected"
|
||||
print(" ✅ Conservative optimization scoring works")
|
||||
|
||||
# Test Case 4: Accuracy improvement (rare but possible)
|
||||
optimized_better = {'latency': 80.0, 'memory': 10.0, 'accuracy': 0.91}
|
||||
scores_better = calculate_normalized_scores(baseline, optimized_better)
|
||||
|
||||
assert scores_better['accuracy_delta'] > 0, "Accuracy improvement not detected"
|
||||
print(" ✅ Accuracy improvement scoring works")
|
||||
|
||||
print("📈 Progress: Normalized Scoring ✓\n")
|
||||
|
||||
test_unit_normalized_scoring()
|
||||
|
||||
# %% [markdown]
|
||||
"""
|
||||
### Key Takeaways
|
||||
|
||||
1. **Always report relative improvements, not absolute numbers**
|
||||
2. **Speedup and compression ratio are the primary metrics**
|
||||
3. **Accuracy delta shows the optimization cost**
|
||||
4. **Efficiency score balances all factors for All-Around event**
|
||||
|
||||
**In Module 20**, you'll use `calculate_normalized_scores()` to generate your competition submission!
|
||||
"""
|
||||
|
||||
# %% [markdown]
|
||||
"""
|
||||
## 4.6 Combination Strategies - Preparing for TorchPerf Olympics
|
||||
## 4.5 Combination Strategies - Preparing for TorchPerf Olympics
|
||||
|
||||
You've learned individual optimizations (M14-18). Now it's time to combine them strategically! The order and parameters matter significantly for final performance.
|
||||
|
||||
@@ -2340,7 +2144,6 @@ def test_module():
|
||||
test_unit_benchmark_suite()
|
||||
test_unit_tinymlperf()
|
||||
test_unit_optimization_comparison()
|
||||
test_unit_normalized_scoring()
|
||||
|
||||
print("\nRunning integration scenarios...")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user