Home Knowledge Base One instruction does a whole matmul.
<svg viewBox="0 0 760 470" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system,Segoe UI,Roboto,sans-serif">
  <rect x="0" y="0" width="760" height="470" fill="#0d1117"/>
  <text x="380" y="28" fill="#e6edf3" font-size="21" font-weight="700" text-anchor="middle">Tensor Core — Matrix Multiply in One Clock</text>
  <text x="380" y="48" fill="#8b98a5" font-size="12" text-anchor="middle">D = A × B + C — a 4×4 matrix multiply-accumulate every cycle, in reduced precision</text>

  <!-- === MAIN: The MMA operation visualized === -->
  <text x="300" y="74" fill="#e6edf3" font-size="12" text-anchor="middle" font-weight="600">One Tensor Core Operation (FP16 example)</text>

  <!-- Matrix A (4x4, left) -->
  <text x="85" y="92" fill="#60a5fa" font-size="10" text-anchor="middle">A (4×4, FP16)</text>
  <g fill="#0f1a2a" stroke="#3b82f6" stroke-width="0.7">
    <rect x="50" y="98" width="18" height="14" rx="1"/><rect x="70" y="98" width="18" height="14" rx="1"/><rect x="90" y="98" width="18" height="14" rx="1"/><rect x="110" y="98" width="18" height="14" rx="1"/>
    <rect x="50" y="114" width="18" height="14" rx="1"/><rect x="70" y="114" width="18" height="14" rx="1"/><rect x="90" y="114" width="18" height="14" rx="1"/><rect x="110" y="114" width="18" height="14" rx="1"/>
    <rect x="50" y="130" width="18" height="14" rx="1"/><rect x="70" y="130" width="18" height="14" rx="1"/><rect x="90" y="130" width="18" height="14" rx="1"/><rect x="110" y="130" width="18" height="14" rx="1"/>
    <rect x="50" y="146" width="18" height="14" rx="1"/><rect x="70" y="146" width="18" height="14" rx="1"/><rect x="90" y="146" width="18" height="14" rx="1"/><rect x="110" y="146" width="18" height="14" rx="1"/>
  </g>
  <!-- Some values inside -->
  <text x="59" y="109" fill="#93c5fd" font-size="6.5" text-anchor="middle">0.3</text>
  <text x="79" y="109" fill="#93c5fd" font-size="6.5" text-anchor="middle">1.2</text>

  <!-- Multiply sign -->
  <text x="145" y="132" fill="#fbbf24" font-size="16" text-anchor="middle">×</text>

  <!-- Matrix B (4x4, top-right) -->
  <text x="215" y="92" fill="#34d399" font-size="10" text-anchor="middle">B (4×4, FP16)</text>
  <g fill="#0f2a1f" stroke="#2f6d55" stroke-width="0.7">
    <rect x="180" y="98" width="18" height="14" rx="1"/><rect x="200" y="98" width="18" height="14" rx="1"/><rect x="220" y="98" width="18" height="14" rx="1"/><rect x="240" y="98" width="18" height="14" rx="1"/>
    <rect x="180" y="114" width="18" height="14" rx="1"/><rect x="200" y="114" width="18" height="14" rx="1"/><rect x="220" y="114" width="18" height="14" rx="1"/><rect x="240" y="114" width="18" height="14" rx="1"/>
    <rect x="180" y="130" width="18" height="14" rx="1"/><rect x="200" y="130" width="18" height="14" rx="1"/><rect x="220" y="130" width="18" height="14" rx="1"/><rect x="240" y="130" width="18" height="14" rx="1"/>
    <rect x="180" y="146" width="18" height="14" rx="1"/><rect x="200" y="146" width="18" height="14" rx="1"/><rect x="220" y="146" width="18" height="14" rx="1"/><rect x="240" y="146" width="18" height="14" rx="1"/>
  </g>

  <!-- Plus sign -->
  <text x="275" y="132" fill="#fbbf24" font-size="16" text-anchor="middle">+</text>

  <!-- Matrix C (accumulator, 4x4, FP32) -->
  <text x="345" y="92" fill="#c4b5fd" font-size="10" text-anchor="middle">C (4×4, FP32)</text>
  <g fill="#1a1520" stroke="#a78bfa" stroke-width="0.7">
    <rect x="310" y="98" width="18" height="14" rx="1"/><rect x="330" y="98" width="18" height="14" rx="1"/><rect x="350" y="98" width="18" height="14" rx="1"/><rect x="370" y="98" width="18" height="14" rx="1"/>
    <rect x="310" y="114" width="18" height="14" rx="1"/><rect x="330" y="114" width="18" height="14" rx="1"/><rect x="350" y="114" width="18" height="14" rx="1"/><rect x="370" y="114" width="18" height="14" rx="1"/>
    <rect x="310" y="130" width="18" height="14" rx="1"/><rect x="330" y="130" width="18" height="14" rx="1"/><rect x="350" y="130" width="18" height="14" rx="1"/><rect x="370" y="130" width="18" height="14" rx="1"/>
    <rect x="310" y="146" width="18" height="14" rx="1"/><rect x="330" y="146" width="18" height="14" rx="1"/><rect x="350" y="146" width="18" height="14" rx="1"/><rect x="370" y="146" width="18" height="14" rx="1"/>
  </g>

  <!-- Equals sign -->
  <text x="405" y="132" fill="#fbbf24" font-size="16" text-anchor="middle">=</text>

  <!-- Result D (4x4, FP32) -->
  <text x="478" y="92" fill="#fbbf24" font-size="10" text-anchor="middle" font-weight="600">D (4×4, FP32)</text>
  <g fill="#2a1a0a" stroke="#f59e0b" stroke-width="0.9">
    <rect x="443" y="98" width="18" height="14" rx="1"/><rect x="463" y="98" width="18" height="14" rx="1"/><rect x="483" y="98" width="18" height="14" rx="1"/><rect x="503" y="98" width="18" height="14" rx="1"/>
    <rect x="443" y="114" width="18" height="14" rx="1"/><rect x="463" y="114" width="18" height="14" rx="1"/><rect x="483" y="114" width="18" height="14" rx="1"/><rect x="503" y="114" width="18" height="14" rx="1"/>
    <rect x="443" y="130" width="18" height="14" rx="1"/><rect x="463" y="130" width="18" height="14" rx="1"/><rect x="483" y="130" width="18" height="14" rx="1"/><rect x="503" y="130" width="18" height="14" rx="1"/>
    <rect x="443" y="146" width="18" height="14" rx="1"/><rect x="463" y="146" width="18" height="14" rx="1"/><rect x="483" y="146" width="18" height="14" rx="1"/><rect x="503" y="146" width="18" height="14" rx="1"/>
  </g>

  <!-- Annotation: FLOPs -->
  <text x="300" y="178" fill="#fbbf24" font-size="10" text-anchor="middle" font-weight="600">= 64 FMA ops in 1 cycle (vs 1 FMA on CUDA core)</text>
  <text x="300" y="193" fill="#8b98a5" font-size="9" text-anchor="middle">input: reduced precision (FP16/BF16/FP8/INT8) — output: full precision (FP32)</text>

  <!-- === RIGHT SIDE: How it maps to neural networks === -->
  <rect x="545" y="74" width="185" height="130" rx="6" fill="#080d14" stroke="#233043" stroke-width="1.2"/>
  <text x="637" y="92" fill="#e6edf3" font-size="10" text-anchor="middle" font-weight="600">Why This Matters for AI</text>
  <text x="560" y="112" fill="#8b98a5" font-size="9">Linear layer = matmul:</text>
  <text x="560" y="128" fill="#93c5fd" font-size="9">Y = X · W + bias</text>
  <text x="560" y="148" fill="#8b98a5" font-size="9">Attention = matmul:</text>
  <text x="560" y="164" fill="#93c5fd" font-size="9">softmax(Q·Kᵀ/√d)·V</text>
  <text x="560" y="184" fill="#6b7684" font-size="8.5">~99% of LLM FLOPs are matmuls</text>
  <text x="560" y="196" fill="#6b7684" font-size="8.5">→ tensor cores do nearly all the work</text>

  <!-- === BOTTOM LEFT: Generation evolution === -->
  <rect x="30" y="210" width="500" height="105" rx="6" fill="#0b1220" stroke="#233043" stroke-width="1"/>
  <text x="280" y="230" fill="#e6edf3" font-size="11" text-anchor="middle" font-weight="600">Tensor Core Generations</text>

  <text x="50" y="252" fill="#6b7684" font-size="9">1st gen (V100):</text>
  <text x="155" y="252" fill="#8b98a5" font-size="9">4×4×4 FP16 → FP32</text>

  <text x="50" y="268" fill="#8b98a5" font-size="9">2nd gen (A100):</text>
  <text x="155" y="268" fill="#8b98a5" font-size="9">+ TF32, BF16, INT8, sparsity (2:4)</text>

  <text x="50" y="284" fill="#c4b5fd" font-size="9">3rd gen (H100):</text>
  <text x="155" y="284" fill="#c4b5fd" font-size="9">+ FP8 (E4M3/E5M2), 989 TF peak</text>

  <text x="50" y="300" fill="#fbbf24" font-size="9" font-weight="600">4th gen (B200):</text>
  <text x="155" y="300" fill="#fbbf24" font-size="9">+ FP4, 2x throughput, 4.5 PF FP8</text>

  <!-- Precision comparison -->
  <rect x="30" y="325" width="500" height="55" rx="5" fill="#0b1220" stroke="#233043" stroke-width="1"/>
  <text x="280" y="345" fill="#e6edf3" font-size="10" text-anchor="middle" font-weight="600">Precision Formats (lower bits = more TOPS)</text>
  <text x="50" y="363" fill="#8b98a5" font-size="9">FP32 (32b): baseline | FP16/BF16 (16b): 2x | TF32 (19b): matmul only | FP8 (8b): 4x | INT8: 4x | FP4: 8x</text>
  <text x="50" y="377" fill="#6b7684" font-size="8.5">Training: BF16 (loss scale) or FP8 (with master weights in FP32). Inference: FP8 or INT8 (sometimes INT4/FP4).</text>

  <!-- === BOTTOM RIGHT: vs CUDA core === -->
  <rect x="545" y="210" width="185" height="170" rx="6" fill="#0b1220" stroke="#233043" stroke-width="1"/>
  <text x="637" y="228" fill="#e6edf3" font-size="10" text-anchor="middle" font-weight="600">Tensor Core vs CUDA Core</text>

  <text x="560" y="250" fill="#60a5fa" font-size="9">CUDA core:</text>
  <text x="560" y="264" fill="#8b98a5" font-size="8.5">1 FMA/cycle (scalar)</text>
  <text x="560" y="278" fill="#8b98a5" font-size="8.5">general purpose</text>
  <text x="560" y="292" fill="#6b7684" font-size="8">good for: branchy code, reductions</text>

  <text x="560" y="314" fill="#fbbf24" font-size="9">Tensor Core:</text>
  <text x="560" y="328" fill="#8b98a5" font-size="8.5">64 FMA/cycle (4×4 matrix)</text>
  <text x="560" y="342" fill="#8b98a5" font-size="8.5">matmul only (fixed function)</text>
  <text x="560" y="356" fill="#6b7684" font-size="8">good for: GEMM, convolution, attention</text>
  <text x="560" y="374" fill="#34d399" font-size="8.5">64x throughput advantage for matmul</text>

  <!-- Footer -->
  <text x="380" y="405" fill="#e6edf3" font-size="9.5" text-anchor="middle" font-weight="600">H100: 528 Tensor Cores × 4 per SM × 132 SMs — running FP8 = ~2000 TFLOPS peak</text>
  <text x="380" y="422" fill="#8b98a5" font-size="9" text-anchor="middle">Real utilization (MFU): 30-50% on LLM training due to memory/communication bottlenecks</text>

  <text x="380" y="450" fill="#6b7684" font-size="10" text-anchor="middle">Tensor Cores are why GPUs dominate AI — they turned a graphics chip into a matrix-math machine.</text>

  <text x="380" y="464" fill="#6b7684" font-size="11" text-anchor="middle">One tensor core = one 4×4 matmul per clock. Stack hundreds of them = petaflops of dense linear algebra.</text>
</svg>
```nsor core is a small matrix-multiply-accumulate engine built into each GPU streaming multiprocessor: in one instruction it multiplies two low-precision matrix tiles and adds them into a higher-precision accumulator — the operation deep learning spends most of its time on.\n\n**One instruction does a whole matmul.** A normal GPU (CUDA) core does one scalar multiply-add per cycle. A tensor core instead consumes two small matrix tiles — on the order of 16 x 16 — and produces D = A x B + C in a few cycles, so a single warp-level MMA instruction retires hundreds of multiply-accumulates. That is why a GPU's tensor-core FLOPS dwarf its general-purpose FLOPS.\n\n**Mixed precision is the trick.** The multiplies run in a low-precision format (FP16, BF16, and on newer parts FP8 or FP4) while the running sum accumulates in FP32. Low precision makes the multipliers small and fast and cuts memory traffic; the wide accumulator keeps the sum from losing accuracy. You get the speed of low precision with much of the stability of high precision.\n\n| GPU generation | Added formats | Notable |\n|---|---|---|\n| Volta (2017) | FP16 mul / FP32 acc | first tensor cores |\n| Turing (2018) | INT8, INT4 | inference |\n| Ampere (A100) | TF32, BF16 | structured sparsity |\n| Hopper (H100) | FP8 | Transformer Engine |\n| Blackwell (B200) | FP4 | 2nd-gen Transformer Engine |\n\n```svg\n<svg viewBox="0 0 1000 540" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif">\n  <rect x="0" y="0" width="1000" height="540" rx="14" fill="#1d1c1a"/>\n  <text x="36" y="40" fill="#e8e6f7" font-size="20" font-weight="600">Tensor core — one instruction computes a whole tile: D = A x B + C</text>\n\n  <!-- A -->\n  <text x="162" y="238" fill="#c9c3f2" font-size="14" text-anchor="middle">A  (FP16/BF16/FP8)</text>\n  <rect x="110" y="250" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <rect x="136" y="250" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <rect x="162" y="250" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <rect x="188" y="250" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <rect x="110" y="276" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <rect x="136" y="276" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <rect x="162" y="276" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <rect x="188" y="276" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <rect x="110" y="302" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <rect x="136" y="302" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <rect x="162" y="302" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <rect x="188" y="302" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <rect x="110" y="328" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <rect x="136" y="328" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <rect x="162" y="328" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <rect x="188" y="328" width="26" height="26" fill="#5b4fc4" fill-opacity="0.85" stroke="#7d70e0" stroke-width="1"/>\n  <!-- B -->\n  <text x="522" y="84" fill="#bff0e4" font-size="14" text-anchor="middle">B  (low precision)</text>\n  <rect x="470" y="96" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <rect x="496" y="96" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <rect x="522" y="96" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <rect x="548" y="96" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <rect x="470" y="122" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <rect x="496" y="122" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <rect x="522" y="122" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <rect x="548" y="122" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <rect x="470" y="148" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <rect x="496" y="148" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <rect x="522" y="148" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <rect x="548" y="148" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <rect x="470" y="174" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <rect x="496" y="174" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <rect x="522" y="174" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <rect x="548" y="174" width="26" height="26" fill="#0f6b5a" fill-opacity="0.85" stroke="#1f9e85" stroke-width="1"/>\n  <!-- D -->\n  <text x="522" y="238" fill="#f0d9b5" font-size="14" text-anchor="middle">D = A x B + C   (FP32 accumulate)</text>\n  <rect x="470" y="250" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n  <rect x="496" y="250" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n  <rect x="522" y="250" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n  <rect x="548" y="250" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n  <rect x="470" y="276" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n  <rect x="496" y="276" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n  <rect x="522" y="276" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n  <rect x="548" y="276" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n  <rect x="470" y="302" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n  <rect x="496" y="302" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n  <rect x="522" y="302" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n  <rect x="548" y="302" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n  <rect x="470" y="328" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n  <rect x="496" y="328" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n  <rect x="522" y="328" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n  <rect x="548" y="328" width="26" height="26" fill="#c98a2e" fill-opacity="0.85" stroke="#e0913a" stroke-width="1"/>\n\n  <!-- flow arrows -->\n  <line x1="222" y1="302" x2="464" y2="302" stroke="#e0913a" stroke-width="2.6"/>\n  <path d="M470 302 l-12 -6 l0 12 Z" fill="#e0913a"/>\n  <line x1="522" y1="206" x2="522" y2="244" stroke="#1f9e85" stroke-width="2.6"/>\n  <path d="M522 250 l-6 -12 l12 0 Z" fill="#1f9e85"/>\n  <text x="345" y="292" fill="#8a8a86" font-size="12" text-anchor="middle">rows of A</text>\n  <text x="560" y="230" fill="#8a8a86" font-size="12">cols of B</text>\n\n  <!-- callouts -->\n  <g font-size="15" fill="#d4d4d0">\n    <text x="700" y="150" fill="#c9c3f2" font-weight="600" font-size="16">One MMA, hundreds of MACs.</text>\n    <text x="700" y="176">A CUDA core does one multiply-add</text>\n    <text x="700" y="197">per cycle; a tensor core eats two</text>\n    <text x="700" y="218">tiles and returns D = A x B + C.</text>\n\n    <text x="700" y="262" fill="#f0d9b5" font-weight="600" font-size="16">Mixed precision.</text>\n    <text x="700" y="288">Multiply in FP16 / BF16 / FP8 (small,</text>\n    <text x="700" y="309">fast); accumulate in FP32 (accurate).</text>\n    <text x="700" y="330">Speed of low precision, stability of high.</text>\n\n    <text x="700" y="374" fill="#bff0e4" font-weight="600" font-size="16">Replicated per SM.</text>\n    <text x="700" y="400">Every streaming multiprocessor has</text>\n    <text x="700" y="421">several, invoked as a warp instruction —</text>\n    <text x="700" y="442">which is why tensor FLOPS dwarf</text>\n    <text x="700" y="463">the GPU's general-purpose FLOPS.</text>\n  </g>\n</svg>\n```\n\n**Tensor core vs systolic array.** Both win the same way — massive operand reuse inside a matrix engine — but the shapes differ. A TPU is one large systolic grid fed by the compiler; a tensor core is a compact MMA unit replicated across every SM and invoked as a GPU instruction over register-file tiles. Nvidia's are the best known, but AMD's CDNA matrix cores and Intel's XMX engines do the same job.\n\nRead the tensor core through a quant lens rather than a marketing lens: a headline PFLOPS number only means something paired with its format (FP16 vs FP8 vs FP4) and whether it counts the 2:1 structured-sparsity mode. What decides real training and inference speed is achievable MACs per byte of HBM traffic at a tolerable precision — the tensor core raises the compute ceiling, but arithmetic intensity and accumulator width decide how much of it you actually reach.
tensor coretensor coresmatrix unitgpu tensor core

Explore 500+ Semiconductor & AI Topics

From EUV lithography to CUDA optimization — search the full knowledge base or chat with our AI assistant.