CoolFace
Apppublic

danyarm/ckg-mcp

sourceHugging Facemitupdated 3mo agoView on Hugging Face
1likes
gpu-inference.html610 linesDownload Raw Back to root
1<!DOCTYPE html>2<html lang="en">3<head>4<meta charset="UTF-8">5<title>GPU → LLM Inference Full Stack — Knowledge Graph · Graphify.md</title>6<style>7*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}8:root{9  --bg:#ffffff;--surface:#f8fafc;--border:#e2e8f0;10  --text:#0f172a;--dim:#64748b;--muted:#94a3b8;11  --nv:#76b900;--nv-lt:#a3e635;--nv-dim:rgba(118,185,0,0.08);--nv-bdr:rgba(118,185,0,0.3);12  --t1:#009485;--t2:#7c3aed;--t3:#94a3b8;13  --hdr:48px;--bot:190px;14}15html,body{width:100%;height:100%;overflow:hidden;background:var(--bg);16  font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;color:var(--text)}17 18/* HEADER */19#hdr{position:fixed;top:0;left:0;right:0;height:var(--hdr);20  background:#ffffff;border-bottom:1px solid var(--border);21  display:flex;align-items:center;gap:12px;padding:0 20px;z-index:100;22  box-shadow:0 1px 3px rgba(0,0,0,.06)}23.h-logo{display:flex;align-items:center;gap:10px;flex-shrink:0}24.h-wordmark{font-size:13px;font-weight:800;letter-spacing:.01em;color:var(--nv)}25.h-dot{width:3px;height:3px;border-radius:50%;background:var(--border);flex-shrink:0}26.h-title{font-size:12px;font-weight:600;color:var(--text);white-space:nowrap}27.h-sub{font-size:9px;color:var(--dim);white-space:nowrap}28.h-fill{flex:1}29.tier-btns{display:flex;gap:5px}30.tbtn{padding:3px 10px;border-radius:5px;font-size:10px;font-weight:700;31  border:1px solid;cursor:pointer;transition:all .15s;background:transparent}32.tbtn[data-tier="1"]{border-color:var(--nv);color:var(--nv)}33.tbtn[data-tier="2"]{border-color:var(--t2);color:var(--t2)}34.tbtn[data-tier="3"]{border-color:var(--border);color:var(--dim)}35.tbtn.on[data-tier="1"]{background:var(--nv);color:#fff}36.tbtn.on[data-tier="2"]{background:var(--t2);color:#fff}37.tbtn.on[data-tier="3"]{background:var(--dim);color:#fff}38.path-sel{background:#fff;border:1px solid var(--border);border-radius:5px;39  color:var(--dim);font-size:10px;padding:3px 8px;cursor:pointer;margin-left:6px}40.path-sel option{background:#fff}41.h-sep{width:1px;height:20px;background:var(--border);flex-shrink:0}42.h-badge{font-size:9px;font-weight:700;padding:3px 8px;border-radius:4px;43  background:var(--nv-dim);border:1px solid var(--nv-bdr);color:var(--nv)}44 45/* GRAPH */46#wrap{position:fixed;top:var(--hdr);left:0;right:0;bottom:var(--bot);background:var(--bg)}47svg{width:100%;height:100%}48 49/* NODE FLOAT */50#node-float{position:absolute;top:14px;left:14px;width:230px;51  background:rgba(255,255,255,.97);border:1px solid var(--border);border-radius:9px;52  padding:12px 14px;display:none;pointer-events:none;53  box-shadow:0 4px 12px rgba(0,0,0,.09)}54.nf-name{font-size:13px;font-weight:700;color:var(--text);margin-bottom:3px;line-height:1.3}55.nf-type{font-size:8px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;margin-bottom:5px}56.nf-desc{font-size:10px;color:var(--dim);line-height:1.55;margin-bottom:5px}57.nf-perf{font-size:9px;color:#b45309;font-weight:700}58.nf-tier{font-size:8px;color:var(--muted);margin-top:4px}59 60/* LEGEND */61#legend-float{position:absolute;top:14px;right:14px;background:rgba(255,255,255,.97);62  border:1px solid var(--border);border-radius:9px;padding:12px 14px;pointer-events:auto;63  box-shadow:0 2px 8px rgba(0,0,0,.07)}64.lf-title{font-size:8px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;65  color:var(--dim);margin-bottom:8px}66.lf-row{display:flex;align-items:center;gap:7px;margin-bottom:5px;cursor:pointer;67  padding:2px 4px;border-radius:4px;transition:background .1s}68.lf-row:hover{background:var(--surface)}69.lf-row.off{opacity:.3}70.lf-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}71.lf-label{font-size:9.5px;color:var(--text)}72.tier-strip{display:flex;gap:10px;margin-top:8px;padding-top:8px;border-top:1px solid var(--border)}73.ts-item{display:flex;align-items:center;gap:5px;font-size:9px;color:var(--dim)}74 75/* BOTTOM STRIP */76#bot{position:fixed;bottom:0;left:0;right:0;height:var(--bot);77  background:#fff;border-top:2px solid var(--border);78  display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:0;overflow:hidden}79.bot-card{border-right:1px solid var(--border);padding:14px 18px;cursor:pointer;80  transition:background .15s;position:relative;overflow:hidden}81.bot-card:last-child{border-right:none}82.bot-card:hover{background:var(--surface)}83.bot-card.active{background:rgba(118,185,0,.04);border-top:2px solid var(--nv);margin-top:-2px}84.bc-num{font-size:8px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;85  color:var(--dim);margin-bottom:4px}86.bc-title{font-size:12px;font-weight:700;color:var(--text);margin-bottom:6px;line-height:1.3}87.bc-body{font-size:10px;color:var(--dim);line-height:1.6}88.bc-perf{font-size:9px;color:#b45309;font-weight:700;margin-top:6px}89.bc-stack{margin-top:8px}90.bc-sys{font-size:11px;font-weight:700;margin-bottom:2px}91.bc-req{font-size:9px;color:var(--dim);line-height:1.5;margin-bottom:4px}92.bc-req span{background:#f1f5f9;padding:1px 5px;border-radius:3px;font-family:monospace;font-size:8px;color:var(--text)}93</style>94</head>95<body>96 97<!-- HEADER -->98<div id="hdr">99  <div>100    <div class="h-title">GPU → LLM Inference Full Stack — Knowledge Graph</div>101    <div class="h-sub">H100 · CUDA · FlashAttention · KV Cache · vLLM · SGLang · TRT-LLM · 85 nodes · 140+ edges · 9 domains</div>102  </div>103  <div class="h-fill"></div>104  <div class="tier-btns">105    <button class="tbtn on" data-tier="1">Tier 1</button>106    <button class="tbtn on" data-tier="2">Tier 2</button>107    <button class="tbtn on" data-tier="3">Tier 3</button>108  </div>109  <select class="path-sel" id="path-sel">110    <option value="">All nodes</option>111    <option value="hardware">Hardware path</option>112    <option value="latency">Latency path</option>113    <option value="throughput">Throughput path</option>114    <option value="memory">Memory path</option>115  </select>116  <div class="h-sep"></div>117  <div class="h-badge">85 nodes · 9 domains</div>118</div>119 120<!-- GRAPH -->121<div id="wrap">122  <svg id="svg"></svg>123  <div id="legend-float">124    <div class="lf-title">Domains</div>125    <div id="lf-rows"></div>126    <div class="tier-strip">127      <div class="ts-item"><svg width="11" height="11"><circle cx="5.5" cy="5.5" r="5.5" fill="#64748b" opacity=".6"/></svg>Tier 1</div>128      <div class="ts-item"><svg width="8" height="8"><circle cx="4" cy="4" r="4" fill="#64748b" opacity=".4"/></svg>Tier 2</div>129      <div class="ts-item"><svg width="6" height="6"><circle cx="3" cy="3" r="3" fill="#64748b" opacity=".25"/></svg>Tier 3</div>130    </div>131  </div>132  <div id="node-float">133    <div class="nf-name" id="nf-name"></div>134    <div class="nf-type" id="nf-type"></div>135    <div class="nf-desc" id="nf-desc"></div>136    <div class="nf-perf" id="nf-perf"></div>137    <div class="nf-tier" id="nf-tier"></div>138  </div>139</div>140 141<!-- BOTTOM STRIP -->142<div id="bot">143  <div class="bot-card" id="ins-0">144    <div class="bc-num">Insight 1 · Hardware Foundation</div>145    <div class="bc-title">Know your roofline before you optimize</div>146    <div class="bc-body">H100: 989 TFLOP/s FP16, 3.35 TB/s HBM3. Ridge = 295 FLOP/byte. Decode is memory-bound; prefill is compute-bound. Every serving optimization is a response to this constraint. Profile the axis before you pick the technique.</div>147    <div class="bc-perf">⬡ H100 vs A100: 3× attention throughput · NVLink 4.0: 900 GB/s all-to-all</div>148  </div>149  <div class="bot-card" id="ins-1">150    <div class="bc-num">Insight 2 · Memory</div>151    <div class="bc-title">The KV cache is the constraint. Everything else is a response</div>152    <div class="bc-body">Decode is 95% memory-bandwidth bound — you pay KV read cost every step. PagedAttention cuts fragmentation to ~0%. MQA/GQA cuts KV size 8×. MLA (DeepSeek-V2) cuts it 8× further via low-rank compression. The whole serving stack traces back to this one bottleneck.</div>153    <div class="bc-perf">⬡ PagedAttention: 20–60% → ~0% waste · Llama-3 70B GQA: 8× KV reduction</div>154  </div>155  <div class="bot-card" id="ins-2">156    <div class="bc-num">Insight 3 · Scheduling</div>157    <div class="bc-title">36.9× from scheduling tokens, not requests</div>158    <div class="bc-body">Orca's 2022 insight: swap sequences at iteration level — finished slots refill immediately. No change to hardware, model, or quantization. Speculative decoding adds 2–4× latency reduction on top: draft K tokens fast, verify all K in one pass with tree attention. Same quality.</div>159    <div class="bc-perf">⬡ Orca OSDI 2022: 36.9× vs static · EAGLE: 3× speedup on LLaMA-2 70B</div>160  </div>161  <div class="bot-card" id="ins-3">162    <div class="bc-num">System Stacks · Why They're Co-dependent</div>163    <div class="bc-title">You cannot deploy one without the full dependency chain</div>164    <div class="bc-stack">165      <div class="bc-sys" style="color:#166534">vLLM</div>166      <div class="bc-req">requires <span>PagedAttention</span> + <span>continuous batching</span> + <span>FlashInfer</span> + <span>preemption</span></div>167      <div class="bc-sys" style="color:#059669">SGLang</div>168      <div class="bc-req">requires <span>RadixAttention</span> + <span>cascade attention</span> + <span>KV sharing</span> + <span>jump-forward</span></div>169      <div class="bc-sys" style="color:#76b900">TensorRT-LLM</div>170      <div class="bc-req">requires <span>FP8 / Transformer Engine</span> + <span>in-flight batching</span> + <span>WGMMA</span> + <span>tensor parallelism</span></div>171    </div>172  </div>173</div>174 175<script src="https://d3js.org/d3.v7.min.js"></script>176<script>177const DOMAINS = [178  {id:'HW',    label:'GPU Hardware',           color:'#76b900', gx:.13, gy:.28},179  {id:'EXEC',  label:'CUDA Execution',         color:'#2563eb', gx:.20, gy:.62},180  {id:'KERN',  label:'Attention Kernels',      color:'#7c3aed', gx:.40, gy:.38},181  {id:'KV',    label:'KV Cache',               color:'#009485', gx:.40, gy:.65},182  {id:'BATCH', label:'Batching & Scheduling',  color:'#059669', gx:.60, gy:.50},183  {id:'OPT',   label:'Quantization & Optim',  color:'#c2410c', gx:.70, gy:.72},184  {id:'SYS',   label:'Serving Systems',        color:'#166534', gx:.82, gy:.42},185  {id:'PARA',  label:'Parallelism',            color:'#4338ca', gx:.68, gy:.18},186  {id:'BENCH', label:'Metrics & Benchmarks',   color:'#475569', gx:.55, gy:.85},187];188const domMap={};189DOMAINS.forEach(d=>domMap[d.id]=d);190const TR={1:11,2:7,3:5};191 192const NODES=[193  // GPU Hardware194  {id:'hw_h100',   label:'NVIDIA H100',             domain:'HW',    tier:1, type:'CHIP',       desc:'Hopper architecture. 80GB HBM3, 3.35 TB/s bandwidth, 989 TFLOP/s FP16, 4th-gen Tensor Cores with FP8 support. The defining inference hardware of 2024–2025.', perf:'989 TFLOP/s FP16 · 3.35 TB/s · 80GB HBM3'},195  {id:'hw_a100',   label:'NVIDIA A100',             domain:'HW',    tier:2, type:'CHIP',       desc:'Ampere architecture. 80GB HBM2e, 2 TB/s, 312 TFLOP/s FP16. Reference baseline for most LLM inference benchmarks.', perf:'312 TFLOP/s FP16 · 2 TB/s · 80GB HBM2e'},196  {id:'hw_te',     label:'Transformer Engine',      domain:'HW',    tier:2, type:'HARDWARE',   desc:'H100/A100 dedicated unit for FP8 matrix multiplications with per-tensor dynamic scaling. Enables 2× throughput vs FP16 with automatic precision management.', perf:'2× throughput vs FP16 on H100'},197  {id:'hw_tc',     label:'4th Gen Tensor Cores',    domain:'HW',    tier:1, type:'HARDWARE',   desc:'H100: native FP8 GEMM. 1979 TFLOP/s TF32, 3958 TFLOP/s FP8. Warp-group matrix multiply (WGMMA) executes asynchronously via TMA.', perf:'3958 TFLOP/s FP8 · 2× FP16 ops vs A100'},198  {id:'hw_hbm3',   label:'HBM3 Memory (3.35 TB/s)', domain:'HW',   tier:2, type:'HARDWARE',   desc:'High-Bandwidth Memory Gen 3. 80GB, 3.35 TB/s bandwidth on H100. Every decode step reads the full KV cache — bandwidth is the binding constraint.', perf:'3.35 TB/s · 10% over A100 HBM2e'},199  {id:'hw_nvlink', label:'NVLink 4.0',              domain:'HW',    tier:2, type:'INTERCONNECT',desc:'900 GB/s bidirectional GPU-GPU bandwidth (H100 DGX). Enables tensor parallelism within a node without PCIe bottleneck.', perf:'900 GB/s · 7× PCIe 5.0 bandwidth'},200  {id:'hw_nvswitch',label:'NVSwitch',               domain:'HW',    tier:3, type:'HARDWARE',   desc:'All-to-all GPU interconnect fabric. DGX H100: 8 GPUs each with 900 GB/s NVLink, all connected via NVSwitch. Eliminates inter-GPU bandwidth bottleneck.'},201  {id:'hw_roofline',label:'Roofline Model',         domain:'HW',    tier:1, type:'MODEL',      desc:'Memory BW ceiling vs compute FLOP/s ceiling. Arithmetic intensity (FLOP/byte) determines which bound applies. H100 ridge: ~295 FLOP/byte. Decode: memory-bound. Prefill: compute-bound.', perf:'H100 ridge point: 295 FLOP/byte'},202  // CUDA Execution203  {id:'ex_cuda',   label:'CUDA Programming Model',  domain:'EXEC',  tier:1, type:'MODEL',      desc:'Grid → Block → Thread hierarchy. SIMT: 32 threads execute same instruction in lockstep (warp). Foundation for all GPU kernel engineering.'},204  {id:'ex_sm',     label:'Streaming Multiprocessor',domain:'EXEC',  tier:1, type:'HARDWARE',   desc:'H100: 132 SMs. Each SM: 128 CUDA cores, 4 warp schedulers, up to 64 active warps, 228KB shared memory. WGMMA ops run per-SM.', perf:'H100: 132 SMs · 228KB SMEM per SM'},205  {id:'ex_warp',   label:'Warp / SIMT Execution',   domain:'EXEC',  tier:1, type:'CONCEPT',    desc:'32 threads executing in lockstep. Warp divergence = serialized branches. Latency hiding: warp scheduler swaps stalled warps immediately — hides HBM latency behind compute.'},206  {id:'ex_smem',   label:'Shared Memory (SMEM)',    domain:'EXEC',  tier:2, type:'RESOURCE',   desc:'On-chip scratchpad per SM. 228KB on H100. ~19× faster than HBM3. FlashAttention tiles KQ/V blocks into SMEM to eliminate O(N²) HBM writes.', perf:'~19× faster than HBM · 228KB per SM H100'},207  {id:'ex_occ',    label:'Occupancy',               domain:'EXEC',  tier:2, type:'METRIC',     desc:'Active warps / max warps per SM. Limited by register file and SMEM usage per thread block. Higher occupancy hides latency better but may reduce per-warp resource budget.'},208  {id:'ex_coal',   label:'Memory Coalescing',       domain:'EXEC',  tier:2, type:'TECHNIQUE',  desc:'32 threads in a warp accessing consecutive, aligned global memory addresses merge into a single 128-byte transaction. Non-coalesced access costs 32 separate transactions.'},209  {id:'ex_async',  label:'Async Copies (cp.async)', domain:'EXEC',  tier:3, type:'INSTRUCTION', desc:'Transfer global → SMEM without stalling the warp. Overlaps compute and memory stages. Used in FlashAttention-3 software pipelining.'},210  {id:'ex_graphs', label:'CUDA Graphs',             domain:'EXEC',  tier:3, type:'TECHNIQUE',  desc:'Pre-record full kernel launch sequence as graph, replay without CPU overhead. Reduces kernel launch latency from ~5μs to <1μs per launch. Critical for small batches.'},211  // Attention Kernels212  {id:'k_mha',     label:'Multi-Head Attention',    domain:'KERN',  tier:1, type:'ALGORITHM',  desc:'Q×K^T÷√d → softmax → ×V per head. Naive: O(N²) HBM writes per layer per step. Prefill: compute-bound. Decode: single-query, memory-bandwidth-bound KV read.'},213  {id:'k_fa2',     label:'FlashAttention-2',        domain:'KERN',  tier:1, type:'ALGORITHM',  desc:'IO-aware tiled attention. Tiles Q, K, V into SMEM blocks; online softmax eliminates O(N²) HBM. 2× FA1, 73% A100 peak FLOP/s on prefill. Used by all major serving systems.', perf:'73% A100 peak · 2× FA1 · O(N) HBM vs O(N²)'},214  {id:'k_fa3',     label:'FlashAttention-3',        domain:'KERN',  tier:1, type:'ALGORITHM',  desc:'Hopper-specific: WGMMA async pipeline, FP8, overlapped GEMM+softmax. ~75% H100 peak on prefill. TMA-based SMEM transfers, 1.5–2× FA2.', perf:'~75% H100 FP16 peak · 1.5–2× FA2'},215  {id:'k_wgmma',   label:'WGMMA Instruction',      domain:'KERN',  tier:2, type:'INSTRUCTION', desc:'H100 Hopper: Warp-Group Matrix Multiply-Accumulate. Operates on warp-group register files asynchronously. Native to FlashAttention-3 and TRT-LLM kernels.'},216  {id:'k_flashinfer',label:'FlashInfer',            domain:'KERN',  tier:1, type:'FRAMEWORK',  desc:'Unified attention kernel library: paged + cascade + FA3 + KV quantization. MLSys 2025 Best Paper. Used by vLLM (v0.5+) and SGLang as drop-in attention backend.', perf:'MLSys 2025 Best Paper · all-in-one attention backend'},217  {id:'k_cascade', label:'Cascade Attention',       domain:'KERN',  tier:2, type:'ALGORITHM',  desc:'Two-pass attention: first pass over shared prefix KV (cached), second pass over unique suffix. Enables prefix KV reuse without reprocessing shared tokens in every request.'},218  {id:'k_gqa_k',   label:'GQA Decode Kernel',      domain:'KERN',  tier:2, type:'COMPONENT',  desc:'Decode attention kernel optimized for grouped-query attention: broadcast fewer KV heads across Q groups. Reads fewer bytes from HBM per decode step vs full MHA.'},219  {id:'k_paged_k', label:'Paged Attention Kernel',  domain:'KERN',  tier:3, type:'COMPONENT',  desc:'Custom CUDA kernel for attention over non-contiguous block-table KV layout. Block-sparse by construction. Now largely replaced by FlashInfer in production stacks.'},220  // KV Cache221  {id:'kv_fund',   label:'KV Cache',               domain:'KV',    tier:1, type:'CONCEPT',    desc:'K and V tensors from attention stored per-layer per-token. Eliminates recomputation during autoregressive decoding. Central bottleneck: every decode step reads full KV across all layers.', perf:'Decode: 95% memory-bandwidth bound · ∝ seq_len × layers × heads'},222  {id:'kv_mqa',    label:'MQA / GQA',              domain:'KV',    tier:1, type:'TECHNIQUE',  desc:'MQA: 1 KV head shared across all Q heads. GQA: groups of Q heads share one KV head. Llama-3 70B: 8 KV heads vs 64 Q = 8× KV size reduction on every decode read.', perf:'Llama-3 70B: 8× KV size reduction'},223  {id:'kv_paged',  label:'PagedAttention',         domain:'KV',    tier:1, type:'ALGORITHM',  desc:'Non-contiguous KV storage via fixed-size blocks + block table. Eliminates internal and external fragmentation. Static allocation wastes 20–60% VRAM; PagedAttention → ~0%.', perf:'Fragmentation: 20–60% → ~0% · vLLM SOSP 2023'},224  {id:'kv_block',  label:'Block Table',            domain:'KV',    tier:2, type:'STRUCTURE',  desc:'Per-sequence virtual-to-physical KV block mapping. Enables non-contiguous storage and copy-on-write prefix sharing. Core data structure of all paged-KV serving systems.'},225  {id:'kv_cow',    label:'Copy-on-Write KV Sharing',domain:'KV',   tier:2, type:'TECHNIQUE',  desc:'Multiple sequences share physical KV blocks for common prefixes (system prompt). Block copied only on write. Eliminates redundant KV computation for shared prefixes.'},226  {id:'kv_radix',  label:'Radix Tree Prefix Cache',domain:'KV',    tier:2, type:'STRUCTURE',  desc:'Trie of KV blocks keyed by token sequence. Automatic prefix reuse across requests. SGLang RadixAttention: 3–5× faster than vLLM on prefix-heavy workloads (chatbot, code).', perf:'SGLang: 3–5× vLLM on prefix-sharing workloads'},227  {id:'kv_quant',  label:'KV Quantization INT8/FP8',domain:'KV',   tier:2, type:'TECHNIQUE',  desc:'Quantize stored K, V tensors to INT8 or FP8. Halves KV memory footprint, doubles concurrent sequences at same VRAM. FlashInfer and TRT-LLM native support.', perf:'2× KV capacity · <0.5% quality degradation'},228  {id:'kv_mla',    label:'MLA — Multi-Head Latent',domain:'KV',    tier:2, type:'ALGORITHM',  desc:'DeepSeek-V2: compress K,V into a low-rank latent vector (joint KV compression). Decompress at inference time. 8× KV cache reduction vs standard MHA.', perf:'8× KV reduction · DeepSeek-V2 · low-rank joint compression'},229  {id:'kv_offload',label:'KV Offload (CPU/NVMe)',  domain:'KV',    tier:3, type:'TECHNIQUE',  desc:'Spill cold KV blocks to CPU RAM or NVMe when VRAM exhausted. Enables longer context or more concurrent sequences at PCIe bandwidth latency cost (~1–3ms per swap).'},230  // Batching & Scheduling231  {id:'b_cont',    label:'Continuous Batching',    domain:'BATCH', tier:1, type:'ALGORITHM',  desc:'Iteration-level scheduling: swap finished sequences out, new ones in, at every decode step. GPU slots never idle. First demonstrated by Orca (OSDI 2022) with 36.9× over static batching.', perf:'36.9× over static batching (Orca OSDI 2022)'},232  {id:'b_spec',    label:'Speculative Decoding',   domain:'BATCH', tier:1, type:'ALGORITHM',  desc:'Draft model generates K candidates; target model verifies all K in one forward pass using tree attention. Accept tokens whose distribution matches target. 2–4× latency reduction, zero quality loss.', perf:'2–4× TPOT reduction · zero quality degradation'},233  {id:'b_ifl',     label:'In-Flight Batching',     domain:'BATCH', tier:1, type:'ALGORITHM',  desc:'TRT-LLM implementation of continuous batching. Integrates with NVIDIA Triton Inference Server for production deployment. Adds dynamic request management and priority handling.'},234  {id:'b_chunked', label:'Chunked Prefill',        domain:'BATCH', tier:2, type:'TECHNIQUE',  desc:'Split long prompt prefills into chunks, interleave with decode steps. Prevents long prefills from head-of-line blocking decode for other users. Reduces P99 TTFT spikes.', perf:'Reduces P99 TTFT spikes on mixed workloads'},235  {id:'b_iter',    label:'Iteration-Level Scheduler',domain:'BATCH',tier:2, type:'COMPONENT', desc:'Per-decode-step decision: which sequences run, which are preempted, which new requests enter. Eliminates head-of-line blocking from static batching. Core of continuous batching.'},236  {id:'b_preempt', label:'Preemption',             domain:'BATCH', tier:2, type:'MECHANISM',  desc:'When VRAM exhausted, evict lower-priority sequences. Two strategies: swap KV blocks to CPU RAM (add PCIe latency), or drop and recompute prefill. Enables VRAM oversubscription.'},237  {id:'b_eagle',   label:'EAGLE / Speculative Heads',domain:'BATCH',tier:2, type:'SYSTEM',   desc:'EAGLE: auto-regressive draft head using target model feature vectors. Higher acceptance rate than separate small LM. EAGLE-2 adds dynamic draft depth. vLLM and SGLang supported.', perf:'EAGLE: 3× speedup on LLaMA-2 70B · EAGLE-2: 3.5×'},238  {id:'b_disagg',  label:'Prefill/Decode Disaggregation',domain:'BATCH',tier:3,type:'ARCHITECTURE',desc:'Separate GPU pools: prefill fleet (compute-bound, large batches) and decode fleet (memory-bound, small batches). Each optimized independently. Reduces prefill-decode resource conflict.'},239  {id:'b_static',  label:'Static Batching',        domain:'BATCH', tier:3, type:'APPROACH',   desc:'Group requests by max sequence length, run until all complete. GPU idles waiting for slowest sequence. Head-of-line blocking. Baseline for all throughput improvement measurements.'},240  // Quantization & Optimization241  {id:'o_fp8',     label:'FP8 Inference',          domain:'OPT',   tier:1, type:'FORMAT',     desc:'FP8 weights + activations on H100 Hopper/Blackwell via Transformer Engine. 2× throughput vs FP16. Native to TRT-LLM and DeepSeek. Requires careful per-tensor calibration.', perf:'2× throughput vs FP16 · H100 native'},242  {id:'o_awq',     label:'AWQ — Activation-Aware WQ',domain:'OPT', tier:2, type:'TECHNIQUE',  desc:'INT4 weight-only quantization guided by activation magnitude. Protects salient channels. 4× weight compression, near-lossless quality, faster than GPTQ. Widely supported.', perf:'4× weight compression · <1% perplexity loss'},243  {id:'o_gptq',    label:'GPTQ',                   domain:'OPT',   tier:2, type:'TECHNIQUE',  desc:'Post-training INT4 quantization via second-order Hessian information. One-shot per-layer compression. Works well on 70B+ models. Slower than AWQ but better for very large models.', perf:'INT4 at near-FP16 quality on 70B+ models'},244  {id:'o_sq',      label:'SmoothQuant (W8A8)',      domain:'OPT',   tier:3, type:'TECHNIQUE',  desc:'Migrate outlier quantization difficulty from activations to weights via per-channel scaling. Enables simultaneous INT8 weights + INT8 activations (W8A8) without quality loss.'},245  {id:'o_sparsity',label:'Structured Sparsity (2:4)',domain:'OPT',  tier:3, type:'TECHNIQUE',  desc:'2 out of every 4 weights are zero. Ampere+ sparse tensor cores: 2× FLOP/s at 50% sparsity. Negligible quality loss at most model sizes when combined with distillation.'},246  {id:'o_gguf',    label:'GGUF / llama.cpp',        domain:'OPT',   tier:2, type:'FORMAT',     desc:'CPU-first quantization format (Q4_K_M, Q5_K_S etc). Enables local inference on consumer hardware. Incompatible with GPU serving stacks but critical for local/edge deployment.'},247  // Serving Systems248  {id:'s_vllm',    label:'vLLM',                   domain:'SYS',   tier:1, type:'SYSTEM',     desc:'Most widely deployed OSS LLM serving engine. Pioneered PagedAttention (SOSP 2023). Async continuous batching, tensor parallelism, FlashInfer backend, multi-model support.', perf:'SOSP 2023 Best Paper · PagedAttention pioneer'},249  {id:'s_sglang',  label:'SGLang',                 domain:'SYS',   tier:1, type:'SYSTEM',     desc:'RadixAttention + structured generation (grammar-constrained decoding). 3–5× faster than vLLM on prefix-heavy and structured output workloads. FlashInfer + cascade attention.', perf:'3–5× vLLM on prefix-sharing · MLSys 2025'},250  {id:'s_trt',     label:'TensorRT-LLM',           domain:'SYS',   tier:1, type:'SYSTEM',     desc:'NVIDIA inference library. FP8 via Transformer Engine, kernel fusion, custom attention plugins, in-flight batching. Highest raw throughput on NVIDIA hardware for production workloads.', perf:'Highest H100 FLOP utilization · NVIDIA optimized'},251  {id:'s_nim',     label:'NVIDIA NIM',             domain:'SYS',   tier:2, type:'PRODUCT',    desc:'Containerized TRT-LLM deployment packaged as enterprise inference microservice. Adds auth, telemetry, SLA monitoring, and multi-model routing on top of TRT-LLM.'},252  {id:'s_triton',  label:'Triton Inference Server',domain:'SYS',   tier:2, type:'SYSTEM',     desc:'NVIDIA production serving infrastructure. Multi-model routing, dynamic batching, gRPC/REST API, model versioning. TRT-LLM plugs in as backend. Used in NVIDIA NIM.'},253  {id:'s_lmd',     label:'LMDeploy / TurboMind',   domain:'SYS',   tier:2, type:'SYSTEM',     desc:'MMLab serving engine. TurboMind kernel: efficient GQA decode attention. AWQ native. Popular for Qwen and InternLM model families. Faster than vLLM on GQA decode.'},254  {id:'s_mlc',     label:'MLC-LLM',                domain:'SYS',   tier:3, type:'SYSTEM',     desc:'TVM compiler-based: compile any model to any target (GPU/CPU/mobile/browser). WebLLM runs full LLMs in browser via WebGPU. Flexible compilation but slower to iterate than vLLM.'},255  // Parallelism256  {id:'p_tp',      label:'Tensor Parallelism',     domain:'PARA',  tier:1, type:'TECHNIQUE',  desc:'Split attention heads and FFN weight matrices across GPUs (Megatron-style). 8-GPU H100: each GPU handles ~1/8 of attention. NVLink required for all-reduce at < 5ms.', perf:'Required for 70B+ on <8 GPUs · NVLink required'},257  {id:'p_pp',      label:'Pipeline Parallelism',   domain:'PARA',  tier:2, type:'TECHNIQUE',  desc:'Split transformer layers into stages across GPUs. Stage N processes batch while Stage N+1 processes previous batch. Pipeline bubbles (idle time at stage boundaries) are wasted compute.'},258  {id:'p_sp',      label:'Sequence Parallelism',   domain:'PARA',  tier:2, type:'TECHNIQUE',  desc:'Distribute sequence tokens across GPUs during attention. Reduces per-GPU activation memory for long contexts. Used alongside tensor parallelism in Megatron-LM.'},259  {id:'p_multi',   label:'Multi-GPU Inference',    domain:'PARA',  tier:1, type:'ARCHITECTURE',desc:'Serving 70B+ models across 2–8 GPUs via tensor and/or pipeline parallelism. H100 DGX node: 8× 80GB = 640GB capacity. NVLink 4.0 keeps all-reduce < 5ms at 70B scale.', perf:'H100 DGX: 8× 80GB = 640GB · NVLink < 5ms allreduce'},260  {id:'p_ep',      label:'Expert Parallelism (MoE)',domain:'PARA', tier:2, type:'TECHNIQUE',  desc:'Mixture-of-Experts: route tokens to subset of expert FFN layers on different GPUs. Each GPU hosts a subset of experts. Used in Mixtral, DeepSeek-V3, GPT-4.'},261  {id:'p_nccl',    label:'NCCL AllReduce',          domain:'PARA', tier:3, type:'LIBRARY',    desc:'NVIDIA Collective Communications Library. Implements all-reduce, all-gather for tensor parallelism sync. Ring or tree algorithm. NVLink rings achieve near-peak bandwidth.'},262  // Metrics263  {id:'m_ttft',    label:'TTFT — Time to First Token',domain:'BENCH',tier:1,type:'METRIC',   desc:'Latency from request submit to first output token. Dominated by prefill compute. Long prompts = high TTFT. Chunked prefill and prefill/decode disaggregation are the levers.', perf:'P99 SLA target: <2s · chunked prefill reduces spikes'},264  {id:'m_tpot',    label:'TPOT / ITL',              domain:'BENCH', tier:1, type:'METRIC',    desc:'Time Per Output Token / Inter-Token Latency. Determined by KV cache memory bandwidth. TPOT ∝ KV cache size × 1/bandwidth. Speculative decoding and MQA/GQA are the levers.', perf:'TPOT ∝ KV size · P99 SLA target: <50ms'},265  {id:'m_tput',    label:'Throughput (tok/s)',       domain:'BENCH', tier:1, type:'METRIC',    desc:'Total output tokens/second across all concurrent requests. Primary metric for batch/offline workloads. Maximized by continuous batching + quantization + large batch sizes.'},266  {id:'m_util',    label:'GPU Utilization',          domain:'BENCH', tier:2, type:'METRIC',    desc:'SM active % across all decode steps. Decode: 40–60% typical (memory-bound). Prefill: 70–85%. Low utilization = memory-bound — optimize KV size and batching before hardware.'},267  {id:'m_mfu',     label:'Model FLOP Utilization',   domain:'BENCH', tier:2, type:'METRIC',    desc:'Observed FLOP/s / peak hardware FLOP/s. Decode MFU: 10–30%. Prefill MFU: 50–70%. Low decode MFU is expected (memory-bound) — not a sign of inefficiency in the serving stack.', perf:'Decode MFU: 10–30% (expected) vs prefill: 50–70%'},268  {id:'m_sla',     label:'SLA / P99 Latency',        domain:'BENCH', tier:2, type:'CONCEPT',   desc:'Production SLAs: P50 TTFT <500ms, P99 TTFT <2s, TPOT <50ms. Priority scheduling and chunked prefill are tools to meet P99 under variable load. SLA violation = customer churn.'},269  {id:'m_tco',     label:'Total Cost of Ownership',  domain:'BENCH', tier:2, type:'METRIC',    desc:'$/1M tokens fully loaded. H100 inference: ~$0.006/1k tokens vs RAG at ~$0.013/1k with CKG compression at ~$0.0005/1k correct answer. TCO drives serving architecture decisions.', perf:'CKG vs RAG: ~10× TCO per correct answer'},270  {id:'m_bench',   label:'Benchmark Suites',         domain:'BENCH', tier:3, type:'TOOL',      desc:'Standard: ShareGPT traces (real chat), synthetic Poisson arrivals, Arena conversations. vLLM and SGLang benchmark on same traces. Critical for apples-to-apples comparison.'},271];272 273const EDGES=[274  // HW internal275  {s:'hw_h100', t:'hw_te',      r:'FEATURES'},276  {s:'hw_h100', t:'hw_tc',      r:'FEATURES'},277  {s:'hw_h100', t:'hw_hbm3',    r:'FEATURES'},278  {s:'hw_h100', t:'hw_nvlink',  r:'FEATURES'},279  {s:'hw_a100', t:'hw_tc',      r:'FEATURES_PREV_GEN'},280  {s:'hw_nvlink',t:'hw_nvswitch',r:'AGGREGATED_BY'},281  {s:'hw_h100', t:'hw_roofline',r:'CHARACTERIZED_BY'},282  // EXEC internal283  {s:'ex_cuda',  t:'ex_sm',     r:'EXECUTES_ON'},284  {s:'ex_sm',    t:'ex_warp',   r:'CONTAINS'},285  {s:'ex_sm',    t:'ex_smem',   r:'HAS'},286  {s:'ex_warp',  t:'ex_occ',    r:'DETERMINES'},287  {s:'ex_smem',  t:'ex_coal',   r:'COMPLEMENTS'},288  {s:'ex_async', t:'ex_smem',   r:'TARGETS'},289  {s:'ex_graphs',t:'ex_cuda',   r:'BUILDS_ON'},290  // KERN internal291  {s:'k_mha',    t:'k_fa2',     r:'OPTIMIZED_BY'},292  {s:'k_fa2',    t:'k_fa3',     r:'EXTENDED_BY'},293  {s:'k_fa3',    t:'k_wgmma',   r:'USES'},294  {s:'k_paged_k',t:'k_flashinfer',r:'REPLACED_BY'},295  {s:'k_cascade',t:'k_flashinfer',r:'IMPLEMENTED_IN'},296  {s:'k_mha',    t:'k_gqa_k',   r:'OPTIMIZED_AS'},297  {s:'k_fa2',    t:'k_cascade', r:'COMPLEMENTED_BY'},298  // KV internal299  {s:'kv_fund',  t:'kv_mqa',    r:'REDUCED_BY'},300  {s:'kv_fund',  t:'kv_paged',  r:'MANAGED_BY'},301  {s:'kv_fund',  t:'kv_quant',  r:'COMPRESSED_BY'},302  {s:'kv_fund',  t:'kv_mla',    r:'COMPRESSED_BY'},303  {s:'kv_fund',  t:'kv_offload',r:'EXTENDED_TO'},304  {s:'kv_paged', t:'kv_block',  r:'IMPLEMENTED_VIA'},305  {s:'kv_paged', t:'kv_cow',    r:'ENABLES'},306  {s:'kv_cow',   t:'kv_radix',  r:'GENERALIZED_BY'},307  // BATCH internal308  {s:'b_cont',   t:'b_iter',    r:'REQUIRES'},309  {s:'b_cont',   t:'b_preempt', r:'REQUIRES'},310  {s:'b_chunked',t:'b_cont',    r:'EXTENDS'},311  {s:'b_spec',   t:'b_eagle',   r:'IMPROVED_BY'},312  {s:'b_ifl',    t:'b_cont',    r:'IMPLEMENTS'},313  {s:'b_preempt',t:'b_disagg',  r:'MOTIVATES'},314  {s:'b_static', t:'b_cont',    r:'SUPERSEDED_BY',a:'36.9×'},315  // OPT internal316  {s:'o_sq',     t:'o_fp8',     r:'COMPLEMENTS'},317  {s:'o_awq',    t:'o_gptq',    r:'FASTER_THAN'},318  {s:'o_sparsity',t:'o_fp8',    r:'COMBINED_WITH'},319  // SYS internal320  {s:'s_trt',    t:'s_nim',     r:'PACKAGED_IN'},321  {s:'s_trt',    t:'s_triton',  r:'BACKENDS_TO'},322  {s:'s_vllm',   t:'s_mlc',     r:'ALTERNATIVE_TO'},323  // PARA internal324  {s:'p_tp',     t:'p_multi',   r:'ENABLES'},325  {s:'p_pp',     t:'p_multi',   r:'ENABLES'},326  {s:'p_multi',  t:'p_nccl',    r:'USES'},327  {s:'p_sp',     t:'p_tp',      r:'COMBINED_WITH'},328  // BENCH internal329  {s:'m_tpot',   t:'m_sla',     r:'CONSTRAINED_BY'},330  {s:'m_ttft',   t:'m_sla',     r:'CONSTRAINED_BY'},331  {s:'m_util',   t:'m_mfu',     r:'RELATED_TO'},332  {s:'m_tput',   t:'m_bench',   r:'MEASURED_BY'},333  {s:'m_ttft',   t:'m_bench',   r:'MEASURED_BY'},334  // === CROSS DOMAIN ===335  // HW → EXEC336  {s:'hw_h100',  t:'ex_cuda',   r:'PROGRAMMED_VIA'},337  {s:'hw_h100',  t:'ex_sm',     r:'CONTAINS'},338  // HW → KERN339  {s:'hw_tc',    t:'k_fa3',     r:'ACCELERATES_VIA_WGMMA'},340  {s:'hw_te',    t:'o_fp8',     r:'ENABLES_NATIVE_FP8'},341  {s:'hw_roofline',t:'kv_fund', r:'IDENTIFIES_BOTTLENECK'},342  {s:'hw_roofline',t:'k_mha',   r:'CHARACTERIZES'},343  // HW → PARA344  {s:'hw_nvlink',t:'p_multi',   r:'INTERCONNECTS'},345  {s:'hw_nvswitch',t:'p_multi', r:'SCALES'},346  // EXEC → KERN347  {s:'ex_smem',  t:'k_fa2',     r:'ENABLES_TILING'},348  {s:'ex_smem',  t:'k_fa3',     r:'ENABLES_TILING'},349  {s:'ex_warp',  t:'k_wgmma',   r:'WARP_GROUP_CONTEXT'},350  {s:'ex_async', t:'k_fa3',     r:'SOFTWARE_PIPELINE'},351  // KERN → KV352  {s:'k_fa2',    t:'kv_fund',   r:'PREFILL_ATTENTION'},353  {s:'k_flashinfer',t:'kv_paged',r:'SUPPORTS_PAGED'},354  {s:'k_cascade',t:'kv_cow',    r:'REQUIRES'},355  {s:'k_cascade',t:'kv_radix',  r:'LEVERAGES'},356  {s:'k_gqa_k',  t:'kv_mqa',    r:'IMPLEMENTS_DECODE'},357  {s:'k_paged_k',t:'kv_paged',  r:'IMPLEMENTS'},358  // KV → BATCH359  {s:'kv_fund',  t:'b_cont',    r:'BOTTLENECK_DRIVES'},360  {s:'kv_paged', t:'b_preempt', r:'ENABLES_EVICTION'},361  {s:'kv_block', t:'b_preempt', r:'UNIT_OF_EVICTION'},362  // KV → SYS363  {s:'kv_paged', t:'s_vllm',    r:'PIONEERED_BY'},364  {s:'kv_radix', t:'s_sglang',  r:'IMPLEMENTED_AS_RADIXATTN'},365  {s:'kv_mla',   t:'s_trt',     r:'SUPPORTED_IN'},366  {s:'kv_cow',   t:'s_sglang',  r:'ENABLES'},367  // BATCH → SYS368  {s:'b_cont',   t:'s_vllm',    r:'IMPLEMENTED_IN'},369  {s:'b_cont',   t:'s_sglang',  r:'IMPLEMENTED_IN'},370  {s:'b_ifl',    t:'s_trt',     r:'NATIVE_TO'},371  {s:'b_chunked',t:'s_vllm',    r:'SUPPORTED_IN'},372  {s:'b_chunked',t:'s_sglang',  r:'SUPPORTED_IN'},373  {s:'b_spec',   t:'s_vllm',    r:'INTEGRATED_IN'},374  {s:'b_spec',   t:'s_sglang',  r:'INTEGRATED_IN'},375  {s:'b_eagle',  t:'s_vllm',    r:'SUPPORTED_IN'},376  {s:'b_iter',   t:'s_vllm',    r:'IMPLEMENTS'},377  // OPT → SYS378  {s:'o_fp8',    t:'s_trt',     r:'NATIVE_TO'},379  {s:'o_fp8',    t:'s_vllm',    r:'SUPPORTED_IN'},380  {s:'o_awq',    t:'s_vllm',    r:'SUPPORTED_IN'},381  {s:'o_awq',    t:'s_lmd',     r:'NATIVE_TO'},382  {s:'o_gptq',   t:'s_vllm',    r:'SUPPORTED_IN'},383  {s:'o_sq',     t:'s_trt',     r:'INTEGRATED_IN'},384  // OPT → KV385  {s:'o_fp8',    t:'kv_quant',  r:'APPLIED_TO_KV'},386  // OPT → KERN387  {s:'o_fp8',    t:'k_fa3',     r:'USED_WITH'},388  // PARA → HW389  {s:'p_tp',     t:'hw_nvlink', r:'REQUIRES'},390  // PARA → SYS391  {s:'p_tp',     t:'s_trt',     r:'REQUIRED_FOR_LARGE'},392  {s:'p_multi',  t:'s_vllm',    r:'ENABLED_IN'},393  {s:'p_tp',     t:'s_vllm',    r:'ENABLED_IN'},394  {s:'p_nccl',   t:'s_vllm',    r:'USED_BY'},395  {s:'p_nccl',   t:'s_sglang',  r:'USED_BY'},396  {s:'p_ep',     t:'s_trt',     r:'SUPPORTED_IN'},397  // BENCH → *398  {s:'b_chunked',t:'m_ttft',    r:'REDUCES_SPIKES'},399  {s:'b_spec',   t:'m_tpot',    r:'REDUCES'},400  {s:'b_cont',   t:'m_tput',    r:'MAXIMIZES'},401  {s:'kv_fund',  t:'m_tpot',    r:'DETERMINES'},402  {s:'m_mfu',    t:'m_tput',    r:'CORRELATES'},403  {s:'m_tco',    t:'m_tput',    r:'DRIVEN_BY'},404  // KERN → SYS405  {s:'k_fa2',    t:'s_vllm',    r:'USED_BY'},406  {s:'k_fa2',    t:'s_trt',     r:'USED_BY'},407  {s:'k_flashinfer',t:'s_vllm', r:'BACKEND'},408  {s:'k_flashinfer',t:'s_sglang',r:'BACKEND'},409];410 411const INSIGHT_NODES=[412  new Set(['hw_h100','hw_a100','hw_tc','hw_te','hw_hbm3','hw_nvlink','hw_roofline','ex_cuda','ex_sm','ex_warp','ex_smem','ex_occ','k_fa3','k_wgmma','k_mha','k_fa2','m_mfu','m_util']),413  new Set(['kv_fund','kv_paged','kv_mqa','kv_block','kv_cow','kv_radix','kv_quant','kv_mla','kv_offload','k_gqa_k','k_cascade','k_flashinfer','m_tpot','o_fp8','o_awq','s_vllm','s_sglang']),414  new Set(['b_cont','b_spec','b_ifl','b_chunked','b_iter','b_preempt','b_eagle','b_disagg','s_vllm','s_sglang','s_trt','s_nim','p_tp','p_multi','m_ttft','m_tput','m_sla','m_tco']),415];416 417const PATHS={418  hardware: new Set(['hw_h100','hw_a100','hw_tc','hw_te','hw_hbm3','hw_nvlink','hw_nvswitch','hw_roofline','ex_cuda','ex_sm','ex_warp','ex_smem','ex_occ','ex_coal','k_fa3','k_wgmma','p_tp','p_multi','p_nccl','o_fp8']),419  latency:  new Set(['b_spec','b_eagle','b_chunked','b_disagg','k_cascade','k_flashinfer','kv_mqa','kv_radix','m_ttft','m_tpot','m_sla','s_sglang','s_vllm','s_trt','hw_roofline']),420  throughput:new Set(['b_cont','b_ifl','b_iter','b_preempt','b_static','kv_paged','kv_radix','kv_cow','k_flashinfer','o_fp8','o_awq','p_tp','p_multi','s_vllm','s_sglang','s_trt','m_tput','m_util','m_mfu','m_bench']),421  memory:   new Set(['kv_fund','kv_mqa','kv_mla','kv_quant','kv_offload','kv_paged','kv_block','kv_cow','o_awq','o_gptq','o_sq','o_sparsity','o_fp8','hw_hbm3','hw_roofline','m_tpot','m_tco','b_preempt']),422};423 424let activeTiers=new Set([1,2,3]), activeDomains=new Set(DOMAINS.map(d=>d.id));425let activePath='', locked=null, activeIns=-1;426let _nodeData=[], _linkData=[], _nodeSel, _linkSel, _labelSel;427 428const svg=d3.select('#svg');429const W=()=>document.getElementById('wrap').clientWidth;430const H=()=>document.getElementById('wrap').clientHeight;431const zoom=d3.zoom().scaleExtent([.1,6]).on('zoom',e=>g.attr('transform',e.transform));432svg.call(zoom);433const g=svg.append('g');434const gBg=g.append('g'), gE=g.append('g'), gN=g.append('g');435const defs=svg.append('defs');436DOMAINS.forEach(d=>{437  defs.append('marker').attr('id','a-'+d.id)438    .attr('viewBox','0 -4 8 8').attr('refX',14).attr('markerWidth',5).attr('markerHeight',5).attr('orient','auto')439    .append('path').attr('d','M0,-4L8,0L0,4').attr('fill',d.color).attr('opacity',.35);440});441 442function vNodes(){return NODES.filter(n=>activeTiers.has(n.tier)&&activeDomains.has(n.domain)&&(!activePath||PATHS[activePath]?.has(n.id)));}443function vEdges(ids){return EDGES.filter(e=>ids.has(e.s)&&ids.has(e.t));}444 445let sim;446function build(){447  gBg.selectAll('*').remove(); gE.selectAll('*').remove(); gN.selectAll('*').remove();448  const vn=vNodes(); if(!vn.length) return;449  const ids=new Set(vn.map(n=>n.id));450  const w=W(), h=H();451  _nodeData=vn.map(n=>{452    const d=domMap[n.domain];453    return{...n, x:d.gx*w+(Math.random()-.5)*40, y:d.gy*h+(Math.random()-.5)*40, _cx:d.gx*w, _cy:d.gy*h};454  });455  const nIdx={}; _nodeData.forEach(n=>nIdx[n.id]=n);456  _linkData=vEdges(ids).map(e=>({...e,source:nIdx[e.s],target:nIdx[e.t]})).filter(e=>e.source&&e.target);457 458  _linkSel=gE.selectAll('line').data(_linkData).join('line')459    .attr('stroke',d=>domMap[d.source.domain].color)460    .attr('stroke-opacity',.28).attr('stroke-width',1)461    .attr('marker-end',d=>'url(#a-'+d.source.domain+')');462 463  _nodeSel=gN.selectAll('circle').data(_nodeData).join('circle')464    .attr('r',d=>TR[d.tier]).attr('fill',d=>domMap[d.domain].color)465    .attr('fill-opacity',.88).attr('stroke','#ffffff').attr('stroke-width',d=>d.tier===1?2:1.5)466    .style('cursor','pointer')467    .on('mouseover',(e,d)=>{if(!locked){hl(d);showInfo(d);}})468    .on('mouseout',()=>{if(!locked)resetHL();})469    .on('click',(e,d)=>{470      e.stopPropagation();471      if(locked===d.id){locked=null;resetHL();}472      else{locked=d.id;hl(d);showInfo(d);}473    });474 475  _labelSel=gN.selectAll('text').data(_nodeData).join('text')476    .text(d=>d.label).attr('font-size',d=>d.tier===1?8.5:7)477    .attr('fill',d=>domMap[d.domain].color).attr('fill-opacity',.82)478    .attr('text-anchor','middle').attr('dy',d=>TR[d.tier]+9).attr('pointer-events','none')479    .attr('font-weight',d=>d.tier===1?'700':'400');480 481  svg.on('click',()=>{locked=null;resetHL();});482 483  if(sim) sim.stop();484  sim=d3.forceSimulation(_nodeData)485    .force('link',d3.forceLink(_linkData).id(d=>d.id).distance(52).strength(.13))486    .force('charge',d3.forceManyBody().strength(-180).distanceMax(350))487    .force('cluster',alpha=>{_nodeData.forEach(n=>{n.vx+=(n._cx-n.x)*alpha*.28;n.vy+=(n._cy-n.y)*alpha*.28;});})488    .force('collide',d3.forceCollide(d=>TR[d.tier]+4))489    .alphaDecay(.02)490    .on('tick',()=>{491      _linkSel.attr('x1',d=>d.source.x).attr('y1',d=>d.source.y)492               .attr('x2',d=>d.target.x).attr('y2',d=>d.target.y);493      _nodeSel.attr('cx',d=>d.x).attr('cy',d=>d.y);494      _labelSel.attr('x',d=>d.x).attr('y',d=>d.y);495    });496  setTimeout(fitAll,2000);497  setTimeout(drawHulls,2500);498}499 500function drawHulls(){501  gBg.selectAll('*').remove();502  const byDom={};503  _nodeData.forEach(n=>{if(!byDom[n.domain])byDom[n.domain]=[];byDom[n.domain].push([n.x,n.y]);});504  Object.entries(byDom).forEach(([id,pts])=>{505    if(pts.length<3) return;506    const hull=d3.polygonHull(pts); if(!hull) return;507    const dom=domMap[id];508    const cx=d3.mean(pts,p=>p[0]), cy=d3.mean(pts,p=>p[1]);509    const pad=26;510    const padded=hull.map(p=>{const dx=p[0]-cx,dy=p[1]-cy,l=Math.sqrt(dx*dx+dy*dy)||1;return[p[0]+dx/l*pad,p[1]+dy/l*pad];});511    gBg.append('path').attr('d','M'+padded.join('L')+'Z')512      .attr('fill',dom.color).attr('fill-opacity',.055)513      .attr('stroke',dom.color).attr('stroke-opacity',.22)514      .attr('stroke-width',1.5).attr('stroke-dasharray','5,3');515  });516}517 518function fitAll(){519  if(!_nodeData.length) return;520  const xs=_nodeData.map(n=>n.x),ys=_nodeData.map(n=>n.y);521  const x0=Math.min(...xs)-28,x1=Math.max(...xs)+28;522  const y0=Math.min(...ys)-28,y1=Math.max(...ys)+28;523  const dx=x1-x0,dy=y1-y0,w=W(),h=H();524  const sc=Math.min(w/dx,h/dy)*.86;525  svg.transition().duration(800).call(zoom.transform,526    d3.zoomIdentity.translate((w-dx*sc)/2-x0*sc,(h-dy*sc)/2-y0*sc).scale(sc));527}528 529function hl(d){530  if(!_nodeSel) return;531  const conn=new Set([d.id]);532  _linkSel.each(e=>{if(e.source.id===d.id)conn.add(e.target.id);if(e.target.id===d.id)conn.add(e.source.id);});533  _nodeSel.attr('fill-opacity',n=>conn.has(n.id)?1:.07).attr('r',n=>conn.has(n.id)?TR[n.tier]*1.45:TR[n.tier]);534  _labelSel.attr('fill-opacity',n=>conn.has(n.id)?1:.04);535  _linkSel.attr('stroke-opacity',e=>(e.source.id===d.id||e.target.id===d.id)?.9:.03)536           .attr('stroke-width',e=>(e.source.id===d.id||e.target.id===d.id)?2.5:.5);537}538 539function hlSet(ns){540  if(!_nodeSel) return;541  _nodeSel.attr('fill-opacity',n=>ns.has(n.id)?1:.07).attr('r',n=>ns.has(n.id)?TR[n.tier]*1.45:TR[n.tier]);542  _labelSel.attr('fill-opacity',n=>ns.has(n.id)?1:.04);543  _linkSel.attr('stroke-opacity',e=>(ns.has(e.source.id)&&ns.has(e.target.id))?.9:.03)544           .attr('stroke-width',e=>(ns.has(e.source.id)&&ns.has(e.target.id))?2.5:.5);545}546 547function resetHL(){548  if(!_nodeSel) return;549  _nodeSel.attr('fill-opacity',.9).attr('r',d=>TR[d.tier]);550  _labelSel.attr('fill-opacity',.82);551  _linkSel.attr('stroke-opacity',.28).attr('stroke-width',1);552  document.getElementById('node-float').style.display='none';553}554 555function showInfo(d){556  const dom=domMap[d.domain];557  document.getElementById('nf-name').textContent=d.label;558  document.getElementById('nf-type').textContent=d.type+' · '+dom.label;559  document.getElementById('nf-type').style.color=dom.color;560  document.getElementById('nf-desc').textContent=d.desc;561  document.getElementById('nf-perf').textContent=d.perf?'⬡ '+d.perf:'';562  document.getElementById('nf-tier').textContent='Tier '+d.tier+' · '+['','Foundation','Advanced','Cutting Edge'][d.tier];563  document.getElementById('node-float').style.display='block';564}565 566// Legend567const lfRows=document.getElementById('lf-rows');568DOMAINS.forEach(dom=>{569  const row=document.createElement('div');570  row.className='lf-row'; row.dataset.id=dom.id;571  row.innerHTML=`<div class="lf-dot" style="background:${dom.color}"></div><div class="lf-label">${dom.label}</div>`;572  row.addEventListener('click',e=>{573    e.stopPropagation();574    if(activeDomains.has(dom.id))activeDomains.delete(dom.id);else activeDomains.add(dom.id);575    row.classList.toggle('off',!activeDomains.has(dom.id));576    locked=null;build();577  });578  lfRows.appendChild(row);579});580 581document.querySelectorAll('.tbtn').forEach(btn=>{582  btn.addEventListener('click',()=>{583    const t=+btn.dataset.tier;584    if(activeTiers.has(t))activeTiers.delete(t);else activeTiers.add(t);585    btn.classList.toggle('on',activeTiers.has(t));586    locked=null;build();587  });588});589document.getElementById('path-sel').addEventListener('change',e=>{activePath=e.target.value;locked=null;build();});590 591[0,1,2,3].forEach(i=>{592  const el=document.getElementById('ins-'+i);593  if(!el||i===3) return;594  el.addEventListener('click',()=>{595    if(activeIns===i){activeIns=-1;el.classList.remove('active');locked=null;resetHL();}596    else{597      activeIns=i;598      [0,1,2].forEach(j=>{const e=document.getElementById('ins-'+j);if(e)e.classList.remove('active');});599      el.classList.add('active');600      locked=null;hlSet(INSIGHT_NODES[i]);601    }602  });603});604 605build();606window.addEventListener('resize',()=>{if(sim)build();});607</script>608</body>609</html>610