Skip to content

Commit fccb87c

Browse files
author
committed
Deployed 9c7d3b0 with MkDocs version: 1.6.1
1 parent d663ace commit fccb87c

11 files changed

Lines changed: 189 additions & 178 deletions

File tree

‎optimization/assets/gen_images.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,8 @@ def fig4_warpn_sweep(t):
279279
bars = ax.bar([str(n) for n in valid_ns], valid_tf,
280280
color=valid_colors, width=0.7, edgecolor='none')
281281

282-
ax.axhline(y=337, color=t["orange"], linestyle='--', lw=1.5, alpha=0.7)
283-
ax.text(0.02, 340, "v3 baseline (337)", fontsize=8,
282+
ax.axhline(y=288, color=t["orange"], linestyle='--', lw=1.5, alpha=0.7)
283+
ax.text(0.02, 291, "v3 baseline (288)", fontsize=8,
284284
color=t["orange"], transform=ax.get_yaxis_transform())
285285

286286
ax.axhline(y=447.5, color=t["yellow"], linestyle='--', lw=1.5, alpha=0.7)
@@ -324,7 +324,7 @@ def fig5_optimization_ladder(t):
324324

325325
labels = ["v0\nnaive", "v1\nSMEM", "v2\nTMA+WGMMA",
326326
"v3\nwarpspec", "v4\ntuned", "cuBLAS"]
327-
values = [0.38, 1.51, 284.4, 337.0, 471.3, 447.5]
327+
values = [0.38, 1.51, 284.4, 288.3, 489.9, 447.5]
328328
colors_l = [t["red"], t["orange"], t["blue"],
329329
t["purple"], t["green"], t["yellow"]]
330330

@@ -343,7 +343,7 @@ def fig5_optimization_ladder(t):
343343
ax.text(x_pos, bar.get_y() + bar.get_height()/2, f"{val:.1f}",
344344
va='center', fontsize=10, color=t["text"], fontweight='bold')
345345

346-
speedups = ["", "3.9×", "188×", "1.19×", "1.40×", ""]
346+
speedups = ["", "3.9×", "188×", "1.01×", "1.70×", ""]
347347
for i, s in enumerate(speedups):
348348
if s:
349349
ax.text(max(values[i], values[i-1]) + 40, i, s,
819 Bytes
Loading
770 Bytes
Loading
-849 Bytes
Loading
-924 Bytes
Loading
16 Bytes
Binary file not shown.

‎optimization/dense-gemm-fp16-from-naive/index.html‎

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3202,15 +3202,15 @@ <h2 id="performance-at-a-glance">Performance at a glance<a class="headerlink" hr
32023202
</tr>
32033203
<tr>
32043204
<td>v3: Warp specialization</td>
3205-
<td style="text-align: right;">3.26</td>
3206-
<td style="text-align: right;">337.0</td>
3207-
<td style="text-align: right;">75.3%</td>
3205+
<td style="text-align: right;">3.81</td>
3206+
<td style="text-align: right;">288.3</td>
3207+
<td style="text-align: right;">64.4%</td>
32083208
</tr>
32093209
<tr>
32103210
<td><strong>v4: Production-tuned</strong></td>
3211-
<td style="text-align: right;"><strong>2.35</strong></td>
3212-
<td style="text-align: right;"><strong>471.3</strong></td>
3213-
<td style="text-align: right;"><strong>105.3%</strong></td>
3211+
<td style="text-align: right;"><strong>2.24</strong></td>
3212+
<td style="text-align: right;"><strong>489.9</strong></td>
3213+
<td style="text-align: right;"><strong>109.5%</strong></td>
32143214
</tr>
32153215
<tr>
32163216
<td>cuBLAS (reference)</td>
@@ -3220,7 +3220,7 @@ <h2 id="performance-at-a-glance">Performance at a glance<a class="headerlink" hr
32203220
</tr>
32213221
</tbody>
32223222
</table>
3223-
<p>1240× improvement from v0 to v4 in five steps. Let's see how each one works.</p>
3223+
<p>1289× improvement from v0 to v4 in five steps. Let's see how each one works.</p>
32243224
<hr />
32253225
<h2 id="kernel-0-naive">Kernel 0: Naive<a class="headerlink" href="#kernel-0-naive" title="Permanent link">&para;</a></h2>
32263226
<p><strong>File:</strong> <code>matmul_f16_v0_naive.co</code></p>
@@ -3543,7 +3543,7 @@ <h2 id="kernel-3-warp-specialization">Kernel 3: Warp Specialization<a class="hea
35433543
<p><strong>File:</strong> <code>matmul_f16_v3_warpspec.co</code></p>
35443544
<p>The insight from v2's profile: producer (TMA) and consumer (WGMMA) stall each other. Fix this by giving them separate warpgroups that run concurrently, connected by a software ring buffer in shared memory.</p>
35453545
<pre class="highlight"><code class="language-choreo">// WARP_M=64, WARP_N=128, WARP_K=16
3546-
// TILE_M=128, TILE_K=64, STAGES=1, CONSUMERS=1
3546+
// TILE_M=64, TILE_K=64, STAGES=1, CONSUMERS=1
35473547

35483548
__co__ void matmul(
35493549
global f16 [M, K] lhs,
@@ -3553,23 +3553,26 @@ <h2 id="kernel-3-warp-specialization">Kernel 3: Warp Specialization<a class="hea
35533553
shared event full[STAGES], empty[STAGES];
35543554
shared f16 [TILE_M, TILE_K] lhs_s[STAGES];
35553555
shared f16 [WARP_N, TILE_K] rhs_s[STAGES];
3556+
shared f16 [WARP_M, WARP_N] output_s[CONSUMERS];
35563557

3557-
// 3 warpgroups × 128 threads = 384 threads/block
3558-
parallel wg by 3 : group-4, t by 128 : thread {
3558+
// 2 warpgroups × 128 threads = 256 threads/block
3559+
parallel wg by 2 : group-4, t by 128 : thread {
35593560
// ── Producer (wg=0): one thread drives TMA ──
35603561
inthreads.async (wg == 0 &amp;&amp; t == 0) {
35613562
foreach {iv_k} in [cdiv(K, TILE_K)] {
35623563
stage = iv_k % STAGES;
35633564
wait empty[stage];
35643565
tma.copy.async&lt;full[stage]&gt;.swiz&lt;SWIZ&gt;
3565-
lhs.subspan(TILE_M, TILE_K).at(block_m, iv_k) =&gt; lhs_s[stage];
3566+
lhs.subspan(TILE_M, TILE_K)
3567+
.at(block_m, iv_k) =&gt; lhs_s[stage];
35663568
tma.copy.async&lt;full[stage]&gt;.swiz&lt;SWIZ&gt;
3567-
rhs.subspan(WARP_N, TILE_K).at(block_n, iv_k) =&gt; rhs_s[stage];
3569+
rhs.subspan(WARP_N, TILE_K)
3570+
.at(block_n, iv_k) =&gt; rhs_s[stage];
35683571
trigger full[stage];
35693572
}
35703573
}
35713574

3572-
// ── Consumers (wg&gt;=1): compute WGMMA ──
3575+
// ── Consumer (wg=1): compute WGMMA ──
35733576
inthreads.async (wg &gt;= 1) {
35743577
cidx = wg - 1;
35753578
foreach {s} in [STAGES]
@@ -3581,17 +3584,20 @@ <h2 id="kernel-3-warp-specialization">Kernel 3: Warp Specialization<a class="hea
35813584
wait full[stage];
35823585

35833586
foreach {iv_wk} in [cdiv(TILE_K, WARP_K)] {
3584-
ma = mma.load.swiz&lt;SWIZ&gt;
3585-
lhs_s[stage].subspan(WARP_M, WARP_K).at(cidx, iv_wk);
3586-
mb = mma.load.swiz&lt;SWIZ&gt; rhs_s[stage].chunkat(_, iv_wk);
3587+
ma = mma.load.swiz&lt;SWIZ&gt;
3588+
lhs_s[stage].subspan(WARP_M, WARP_K)
3589+
.at(cidx, iv_wk);
3590+
mb = mma.load.swiz&lt;SWIZ&gt;
3591+
rhs_s[stage].chunkat(_, iv_wk);
35873592
mma.row.row mc, ma, mb;
35883593
}
3594+
mma.commit;
35893595
trigger empty[stage];
35903596
}
3591-
shared f16 [WARP_M, WARP_N] output_s[CONSUMERS];
35923597
mma.store mc, output_s[cidx];
35933598
tma.copy output_s[cidx] =&gt;
3594-
output.subspan(WARP_M, WARP_N).at(block_m * CONSUMERS + cidx, block_n);
3599+
output.subspan(WARP_M, WARP_N)
3600+
.at(block_m * CONSUMERS + cidx, block_n);
35953601
}
35963602

35973603
}
@@ -3639,14 +3645,14 @@ <h3 id="generated-cuda-v3-warpgroup-dispatch">Generated CUDA (v3) — warpgroup
36393645
full[iv_k % STAGES], 1, bytes); // trigger full
36403646
}
36413647
}
3642-
if (wg &gt;= 1) { // consumers
3648+
if (wg &gt;= 1) { // consumer
36433649
for (int iv_k = 0; ...) {
36443650
full[iv_k % STAGES].wait(...); // wait full
36453651
/* WGMMA (same as v2) */
36463652
empty[iv_k % STAGES].arrive(); // trigger empty
36473653
}
36483654
}</code></pre>
3649-
<p><strong>Result: ~337 TFLOPS (1.19× over v2, 75.3% of cuBLAS)</strong></p>
3655+
<p><strong>Result: ~288 TFLOPS (1.01× over v2, 64.4% of cuBLAS)</strong></p>
36503656
<hr />
36513657
<h2 id="kernel-4-production-tuned">Kernel 4: Production-Tuned<a class="headerlink" href="#kernel-4-production-tuned" title="Permanent link">&para;</a></h2>
36523658
<p><strong>File:</strong> <code>matmul_f16_v4_auto_tuned.co</code></p>
@@ -3708,7 +3714,7 @@ <h3 id="ncu-snapshot-v4">NCU snapshot (v4)<a class="headerlink" href="#ncu-snaps
37083714
gpu__dram_throughput (% of HBM BW) : 38.91% ← TMA hiding all loads
37093715
warp occupancy (% of peak) : 27.74% ← ~2 blocks/SM (smem-limited)</code></pre>
37103716
<p>SM and tensor-core utilisation are at 89.7% — the kernel is firmly in the compute-bound regime. DRAM at 39% means TMA is successfully prefetching ahead. Warp occupancy at 27.7% reflects the shared memory footprint (~80 KB per block) allowing 2 concurrent blocks per SM on H800.</p>
3711-
<p><strong>Result: ~471 TFLOPS (1.40× over v3, 105% of cuBLAS on this GPU)</strong></p>
3717+
<p><strong>Result: ~490 TFLOPS (1.70× over v3, 109% of cuBLAS on this GPU)</strong></p>
37123718
<hr />
37133719
<h2 id="the-full-ncu-picture">The full NCU picture<a class="headerlink" href="#the-full-ncu-picture" title="Permanent link">&para;</a></h2>
37143720
<p>Profiled with a single kernel launch (<code>ncu --launch-count 1</code>):</p>
@@ -3754,15 +3760,15 @@ <h2 id="the-full-ncu-picture">The full NCU picture<a class="headerlink" href="#t
37543760
<td style="text-align: right;">56.13</td>
37553761
<td style="text-align: right;">9,418,787</td>
37563762
<td style="text-align: right;">—</td>
3757-
<td style="text-align: right;">337.0</td>
3763+
<td style="text-align: right;">288.3</td>
37583764
</tr>
37593765
<tr>
37603766
<td>v4 tuned</td>
37613767
<td style="text-align: right;">38.91</td>
37623768
<td style="text-align: right;">89.68</td>
37633769
<td style="text-align: right;">9,492,372</td>
37643770
<td style="text-align: right;">—</td>
3765-
<td style="text-align: right;">471.3</td>
3771+
<td style="text-align: right;">489.9</td>
37663772
</tr>
37673773
</tbody>
37683774
</table>
@@ -3784,7 +3790,7 @@ <h2 id="the-full-ncu-picture">The full NCU picture<a class="headerlink" href="#t
37843790
&lt;compiled-kernel-binary&gt;</code></pre>
37853791
<hr />
37863792
<h2 id="the-tuning-journey-v3-v4">The Tuning Journey: v3 → v4<a class="headerlink" href="#the-tuning-journey-v3-v4" title="Permanent link">&para;</a></h2>
3787-
<p>v4 was not designed upfront — it was found by a systematic 28-iteration parameter sweep starting from v3. Here is the actual log. This is the core of the tutorial: the techniques above give you a structurally correct kernel, but the last 40% comes from tuning.</p>
3793+
<p>v4 was not designed upfront — it was found by a systematic 28-iteration parameter sweep starting from v3. Here is the actual log. This is the core of the tutorial: the techniques above give you a structurally correct kernel, but the last 70% comes from tuning.</p>
37883794
<h3 id="baseline-v3-stages1-consumers1-warp_n128">Baseline: v3 (STAGES=1, CONSUMERS=1, WARP_N=128)<a class="headerlink" href="#baseline-v3-stages1-consumers1-warp_n128" title="Permanent link">&para;</a></h3>
37893795
<p>NCU on the v3 baseline reveals the kernel is <strong>latency-bound</strong>:</p>
37903796
<pre class="highlight"><code>sm__throughput: 56% ← SM underutilized
@@ -3807,7 +3813,7 @@ <h3 id="phase-1-pipeline-architecture-iter000-iter003">Phase 1 — Pipeline Arch
38073813
<tr>
38083814
<td>iter000</td>
38093815
<td>baseline (STAGES=1, CONS=1)</td>
3810-
<td style="text-align: right;">337</td>
3816+
<td style="text-align: right;">288</td>
38113817
<td>latency-bound</td>
38123818
</tr>
38133819
<tr>
@@ -3926,9 +3932,9 @@ <h2 id="sota-comparison">SOTA comparison<a class="headerlink" href="#sota-compar
39263932
</tr>
39273933
<tr>
39283934
<td><strong>Croqtile v4 (tuned)</strong></td>
3929-
<td style="text-align: right;"><strong>2.35</strong></td>
3930-
<td style="text-align: right;"><strong>471.3</strong></td>
3931-
<td style="text-align: right;"><strong>105.3%</strong></td>
3935+
<td style="text-align: right;"><strong>2.24</strong></td>
3936+
<td style="text-align: right;"><strong>489.9</strong></td>
3937+
<td style="text-align: right;"><strong>109.5%</strong></td>
39323938
</tr>
39333939
</tbody>
39343940
</table>
@@ -3941,8 +3947,8 @@ <h2 id="sota-comparison">SOTA comparison<a class="headerlink" href="#sota-compar
39413947
<p>All three can be expressed in Croqtile — the production-grade kernels in the repository implement them.</p>
39423948
<hr />
39433949
<h2 id="the-optimization-ladder">The optimization ladder<a class="headerlink" href="#the-optimization-ladder" title="Permanent link">&para;</a></h2>
3944-
<p><img alt="Optimization ladder: TFLOPS progression from v0 (0.38) through v4 (471), compared to cuBLAS (447)" src="../assets/img/optimization_ladder.png#only-dark" />
3945-
<img alt="Optimization ladder: TFLOPS progression from v0 (0.38) through v4 (471), compared to cuBLAS (447)" src="../assets/img/optimization_ladder_light.png#only-light" /></p>
3950+
<p><img alt="Optimization ladder: TFLOPS progression from v0 (0.38) through v4 (490), compared to cuBLAS (447)" src="../assets/img/optimization_ladder.png#only-dark" />
3951+
<img alt="Optimization ladder: TFLOPS progression from v0 (0.38) through v4 (490), compared to cuBLAS (447)" src="../assets/img/optimization_ladder_light.png#only-light" /></p>
39463952
<table>
39473953
<thead>
39483954
<tr>
@@ -3969,13 +3975,13 @@ <h2 id="the-optimization-ladder">The optimization ladder<a class="headerlink" hr
39693975
<td>v2 → v3</td>
39703976
<td>Warp specialization</td>
39713977
<td><code>inthreads.async</code>, <code>shared event</code>, <code>wait/trigger</code></td>
3972-
<td style="text-align: right;">1.19×</td>
3978+
<td style="text-align: right;">1.01×</td>
39733979
</tr>
39743980
<tr>
39753981
<td>v3 → v4</td>
39763982
<td>Pipeline tuning</td>
39773983
<td>STAGES=2, CONSUMERS=2, WARP_N=192 (28-iter sweep)</td>
3978-
<td style="text-align: right;">1.40×</td>
3984+
<td style="text-align: right;">1.70×</td>
39793985
</tr>
39803986
</tbody>
39813987
</table>

‎search/search_index.json‎

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)