惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News: Ask HN
Hacker News: Ask HN
WordPress大学
WordPress大学
H
Help Net Security
小众软件
小众软件
N
Netflix TechBlog - Medium
C
Check Point Blog
量子位
Last Week in AI
Last Week in AI
GbyAI
GbyAI
Martin Fowler
Martin Fowler
M
MIT News - Artificial intelligence
博客园 - 聂微东
Engineering at Meta
Engineering at Meta
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
J
Java Code Geeks
D
DataBreaches.Net
Project Zero
Project Zero
P
Proofpoint News Feed
T
Threat Research - Cisco Blogs
Security Latest
Security Latest
Cisco Talos Blog
Cisco Talos Blog
Recorded Future
Recorded Future
I
Intezer
L
Lohrmann on Cybersecurity
Cyberwarzone
Cyberwarzone
博客园_首页
C
Cyber Attacks, Cyber Crime and Cyber Security
L
LangChain Blog
P
Palo Alto Networks Blog
V
V2EX
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
The Exploit Database - CXSecurity.com
The Hacker News
The Hacker News
Blog — PlanetScale
Blog — PlanetScale
G
GRAHAM CLULEY
T
The Blog of Author Tim Ferriss
C
Cisco Blogs
The Register - Security
The Register - Security
L
LINUX DO - 热门话题
P
Privacy & Cybersecurity Law Blog
Scott Helme
Scott Helme
F
Full Disclosure
博客园 - 司徒正美
Recent Announcements
Recent Announcements
IT之家
IT之家
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Attack and Defense Labs
Attack and Defense Labs
Cloudbric
Cloudbric
Help Net Security
Help Net Security
The Last Watchdog
The Last Watchdog

Hacker News

Introducing Claude Opus 4.7 Qwen Studio The Future of Everything is Lies, I Guess: Where Do We Go From Here? GitHub - SeanFDZ/macmind: Single-layer transformer in HyperTalk for the classic Macintosh Show HN: Agent-cache – Multi-tier LLM/tool/session caching for Valkey and Redis Moving a large-scale metrics pipeline from StatsD to OpenTelemetry / Prometheus GitHub - Nightmare-Eclipse/RedSun: The Red Sun vulnerability repository GitHub - SethPyle376/hiraeth: Local AWS emulator focused on fast integration testing, with SQS support, SQLite-backed state, and a debug-friendly web UI. GitHub - macOS26/Agent: Any AI, replaces Claude Code, Cursor, OpenClaw. Over 18 LLM providers (Claude, OpenAI, Gemini, Ollama, Zai, HF, Qwen) wired into a native Mac app that writes code, builds Xcode projects, bumps versions, manages git, automates Safari, use AppleScript, JS or Accessibility, extend Agent! w/ MCP Servers, run tasks from your iPhone via Messages. YouTube now lets you turn off Shorts I Made a Terminal Pager Burgers | マクドナルド公式 Commands — HackerNews CLI documentation ChatGPT for Excel PiCore - Raspberry Pi Port of Tiny Core Linux Live Nation illegally monopolized ticketing market, jury finds Google Broke Its Promise to Me. Now ICE Has My Data. Founding Engineer at Adaptional | Y Combinator CRISPR takes important step toward silencing Down syndrome’s extra chromosome GitHub - saffron-health/libretto: The AI toolkit for building reliable browser automations US v. Heppner (S.D.N.Y. 2026) no attorney-client privilege for AI chats [pdf] Unexpected €54k billing spike in 13 hours: Firebase browser key without API restrictions used for Gemini requests Retrofitting JIT Compilers into C Interpreters IPv6 – Google The Accursèd Alphabetical Clock Cybersecurity Looks Like Proof of Work Now Fragments: April 14 Cal.com Goes Closed Source: Why AI Security Is Forcing Our Decision | Cal.com - Scheduling Software for Online Bookings Laravel raised money and now injects ads directly into your agent When moving fast, talking is the first thing to break Too much Discussion of the XOR swap trick – Heather Cafe Introduction to Spherical Harmonics for Graphics Programmers The Grand Line Building a Z-Machine in the worst possible language High-Level Rust: Getting 80% of the Benefits with 20% of the Pain GitHub - duguyue100/midnight-captain: Inspired by Midnight Commander, tailored to my taste. How to build a `git diff` driver · Jamie Tanna | Software Engineer Center for Responsible, Decentralized Intelligence at Berkeley The Local Universe’s Expansion Rate Is Clearer Than Ever, but Still Doesn’t Add Up - A new synthesis of astronomical measurements confirms a persistent mismatch that could point to physics beyond current models The air throughout our homes is infused with microplastics. But there are things you can do to breathe less of them The disturbing white paper Red Hat is trying to erase from the internet – OSnews The Future of Everything is Lies, I Guess: Annoyances ‘Abhorrent’: the inside story of the Polymarket gamblers betting millions on war Productive procrastination — Max van IJsselmuiden maps, territory and LMs 447 Terabytes per Square Centimetre at Zero Retention Energy: Non-Volatile Memory at the Atomic Scale on Fluorographane Show HN: Pardonned.com – A searchable database of US Pardons 20 Years on AWS and Never Not My Job The Seasons are Wrong Artemis II crew splashes down near San Diego after historic moon mission We gave an AI a 3 year retail lease in SF and asked it to make a profit | Andon Labs How a dancer with ALS used brainwaves to perform live On filing the corners off my MacBooks Installing every* Firefox extension OpenClaw’s memory is unreliable, and you don’t know when it will break Steve Blank Nowhere Is Safe Chimpanzees in Uganda locked in vicious 'civil war', say researchers watgo - a WebAssembly Toolkit for Go linux/Documentation/process/coding-assistants.rst at master · torvalds/linux GitHub - callumlocke/json-formatter: Makes JSON easy to read. Founding Product Engineer at Bild AI | Y Combinator A compelling title that is cryptic enough to get you to take action on it GitHub - Keychron/Keychron-Keyboards-Hardware-Design: Industrial design files for Keychron keyboards and mice. 100+ models with CAD assets in STEP, DXF, DWG, and PDF. Source-available, with commercial use allowed for original compatible accessories within the license terms. [ANNOUNCE] WireGuardNT v0.11 and WireGuard for Windows v0.6 Released 1D-Chess Helium Is Hard to Replace Cooperative Vectors Introduction | Evolve Keeping a Postgres queue healthy — PlanetScale Our response to the Axios developer tool compromise Do Americans read print books, e-books or audiobooks more? The Zettelkasten Method in Obsidian: A Practical Setup Guide Artemis II Is Competency Porn and We Are Starving For It WeakC4 Flight Viz — Cockpit View A Mexican surveillance giant you’ve never heard of is now watching the U.S. border Surelock: Deadlock-Free Mutexes for Rust RISC-V 101 – what is it and what does it mean for Canonical? | Ubuntu The Problem That Built an Industry How Much Linear Memory Access Is Enough? | Solidean Investigating Split Locks on x86-64 Simplest hash functions Sybilproof reputation mechanisms (2005) [pdf] What is a property? How Complex is my Code? Static code analysis in Kotlin — tools overview Toffoli gates are all you need PGLite evangelism dcmake: a new CMake debugger UI Clojure on Fennel part one: Persistent Data Structures Fragments: April 2 Python Release Python install manager 26.1 The Life and Death of the Book Review - Liberties Introducing Database Traffic Control — PlanetScale Bitcoin miners are losing $19,000 on every BTC produced as difficulty drops 7.8% God sleeps in the minerals Building slogbox Apple Silicon and Virtual Machines: Beating the 2 VM Limit Who was “Not Even Wrong” first? Pokemon Evolution Vs Darwinian Evolution The APL Programming Language Source Code
Integer Quantization: Deep Dive 🤿
Anwaar Khalid · 2026-06-19 · via Hacker News

A lot has happened in transformer quantization over the past few years, from barely being able to quantize a 7B model in INT8 without destroying accuracy, to routinely fitting a 70B model in 4-bits on a single GPU. But existing guides on the topic are fragmented: either focused on a specific technique or on how to use a library. I’ve been working on integer quantization for fixed-point hardware for a while now and my goal with this series is to bridge that gap: building the core ideas carefully and tracing how the field has evolved, each technique motivated by the problems of what came before. This first post covers the foundations: what quantization is, why it’s hard, and the math behind it.

What is Quantization & why should you care?

Quantization is the process of representing high-precision values using fewer bits. In practice, this means storing weights and (optionally) activations in lower precision (e.g., int8 instead of fp16), introducing a small approximation error.

The most immediate and easy-to-realize benefit of quantization is memory reduction. As a rule of thumb, a model with N billion parameters requires roughly 2 × N GB of memory when stored in 16-bit precision. Quantizing to 8-bit or 4-bit reduces this footprint by 2× and 4×, respectively.

There is also a hardware advantage. In 2014, Mark Horowitz, from Stanford University published a paper Computing’s Energy Problem which studied fp operations vs integer operations:

Energy Consumption: Integer vs Floating Point Energy Costs for various operations on a 45nm CMOS node. Source: Computing’s Energy Problem

So, integer arithmetic consumes lesser energy, specifically int8 add consumes 30x less energy than fp32 add & int8 mul consumes 18x less energy than fp32 mul. Lower precision hardware is also faster & consumes lesser silicon area than floating point.

How do these benefits translate to real-world gains? It depends on the bottleneck:

  • Compute-bound workloads (e.g., CNNs, LLM prefill): Quantization can improve throughput since lower-precision arithmetic is faster and consumes lesser energy.

  • Memory-bandwidth-bound workloads (e.g., LLM decoding): Quantization reduces the amount of data moved, improving performance by lowering memory bandwidth pressure.

By this point, the motivation should be clear: quantization reduces memory, lowers energy consumption, and can improve performance. Next, we will look at the hardware unit that executes fixed point arthmetic.

Multiply Accumulate Unit

The dominant operation in neural networks is matrix multiplication. Modern hardware accelerators optimize this using specialized units called Multiply–Accumulate (MAC) Units:

Multiply Accumulate Unit
Matrix–vector computation in neural network accelerator hardware. Source: A White Paper on Neural Network Quantization

The diagram represents a typical matrix–vector multiply unit in neural network accelerators. This is the building block for matrix multiplications and convolutions. The two fundamental components are the processing elements \(C_{n,m}\) and the accumulators \(A_n\).

The computation proceeds as follows:

  • The accumulators are first initialized with the bias value \(b_n\)

  • In the next cycle, weights \(W_{n,m}\) and input values \(x_m\) are loaded

  • Their product is computed at each processing element:

    $$C_{n,m} = W_{n,m} \cdot x_m$$

  • The results are then accumulated:

    $$A_n = b_n + \sum_{m} C_{n,m}$$

How is quantization done?

Starting from a real-valued vector \(x\), we map it to an integer grid \(\{x_{\text{int}}^{\min}, \ldots, x_{\text{int}}^{\max}\}\):

$$ x_{\text{int}} = \mathrm{clamp} \left( \left\lfloor \frac{x}{s} \right\rceil + z,\; x_{\text{int}}^{\min},\; x_{\text{int}}^{\max} \right) $$

Here:

  • \(s\) is the scale

  • \(z\) is the zero-point (offset)

  • \(\lfloor \cdot \rceil\) denotes rounding to the nearest integer

The clamp operation ensures the result lies within the valid integer range:

So, the idea is to scale and shift the floating-point value, then clamp it to fit within the integer grid.

Quantization Simulation (Fake Quantization)

Instead of running quantized models directly on target hardware, we often simulate quantization on general-purpose hardware using high-level frameworks like PyTorch. This is commonly referred to as fake quantization.

The key idea is simple: we mimic the effects of quantization while still executing operations in floating point. This allows us to study accuracy and perform experiments like Quantization Aware Training (QAT) without requiring specialized hardware.

To do this, we:

  1. Quantize the input to an integer grid
  2. Dequantize it back to floating point
  3. Perform all computations in floating point on standard hardware (e.g., GPUs)

The dequantization step maps integers back to real values:

$$ \widehat{\mathbf{x}} = s \left( \mathbf{x}_{\text{int}} - z \right) $$

Combining quantization and dequantization, we get:

$$ \widehat{\mathbf{x}} = q(\mathbf{x}; s, z) = s \left[ \mathrm{clamp} \left( \left\lfloor \frac{\mathbf{x}}{s} \right\rceil + z,\; x_{\text{int}}^{\min},\; x_{\text{int}}^{\max} \right) - z \right] $$

In practice, frameworks insert these quant–dequant (Q/DQ) pairs around operations in the model graph. While the computation is still carried out in floating point, the values are constrained to a discrete set, effectively simulating quantization effects during inference.

What are \(q_{\min}\) & \(q_{\max}\) ?

At this point, it’ll be helpful to build some intuition around what the quantization formula is actually doing.

Think about the minimum value that can come out of the quantization operation.
This corresponds to \(x_{\text{int}}^{\min}\). Plugging this into the de-quantization formula:

$$ q_{\min} = s \left( x_{\text{int}}^{\min} - z \right) $$

Similarly, the maximum value corresponds to \(x_{\text{int}}^{\max}\):

$$ q_{\max} = s \left( x_{\text{int}}^{\max} - z \right) $$

Fake Quantized Grid

Key thing to note here is: we no longer operate over a continuous floating-point range, but over a discrete set of \(2^b\) values, each separated by the scale \(s\).

Quantization Error

There are two “bad guys” in our quantization formula:
(1) the rounding operator, which introduces rounding error, and
(2) the clamp operator, which introduces clipping error.

These are the reasons why a quantized network deviates from the original network, a.k.a: quantization error (or quantization noise). As we’ll see, improving one often worsens the other, so quantization is really about balancing the two.

Rounding Error: for a value is the difference between the original floating-point value and the value it gets mapped to on the quantized grid.

Clipping Error: occurs when values fall outside the representable range and get clipped to the minimum or maximum value.

Let’s think about the extremes again. When would the rounding error be the maximum? The worst case occurs when the fp value lies exactly halfway between two grid points. In this case:

$$ \text{max rounding error} = \frac{s}{2} $$

So, you might think: “why not make \(s\) very small to minimize this for each value?”. Unfortunately, there’s no free lunch when it comes to quantization: reducing s makes [\(q_{\min} = s \left( x_{\text{int}}^{\min} - z \right)\), \(q_{\max} = s \left( x_{\text{int}}^{\max} - z \right)\)] smaller increasing your clipping error.

So how do you choose quantization parameters optimally?

How are quantization params ( scale and offset) calculated?

The simplest approach is min–max quantization, where we use an unsigned integer grid \((0 \text{ to } 2^b - 1)\) and set the scale so that the entire floating-point range fits within it, avoiding clipping. That is, you want:

\(q_{\max}\) to map to \(fp_{\max}\) & \(q_{\min}\) to map to \(fp_{\min}\)

So you solve:

$$ q_{\max} = s \left(2^b - 1 - z\right) = fp_{\max} $$

$$ q_{\min} = -s z = fp_{\min} $$

Solving these gives:

$$ s = \frac{fp_{\max} - fp_{\min}}{2^b - 1} $$

$$ z = \frac{fp_{\min} \cdot (2^b - 1)}{fp_{\min} - fp_{\max}} $$

For a signed grid \((-2^{b-1} \text{ to } 2^{b-1} - 1)\), the corresponding method is abs-max quantization, where we scale using the maximum absolute value so that the range is symmetric around zero, avoiding clipping.

So you solve:

$$ q_{\max} = s \cdot (2^{b-1} - 1) = \max\left( |fp_{\min}|,\; |fp_{\max}| \right) $$

Solving gives:

$$ s = \frac{\max\left( |fp_{\min}|,\; |fp_{\max}| \right)}{2^{b-1} - 1} $$

$$ z = 0 $$

These are the most common formulas for scale and offset on the internet – now you known where they come from!

AbsMax Quantization An example of AbsMax Quantization. Author Maarten Grootendorst

Notice how some of values in integer grid get wasted with AbsMax Quantization.

But what if your tensor contains outliers - i.e., a very small fraction of values have large magnitudes while most are relatively small?

If you use min–max or abs-max quantization, these outliers stretch the range of the grid. As a result, most values get mapped to a coarser grid, leading to higher rounding error.

Fortunately, there are alternatives:

  • Loss-aware quantization:
    Choose the quantization parameters (e.g., range, scale) to minimize a loss between the floating-point and quantized outputs - such as MSE, cross-entropy, or SQNR.

  • Range clipping:
    Instead of covering the full range, clip extreme values (e.g., using percentiles) to reduce the impact of outliers and improve effective resolution.

Even these do not guarentee that quantization will work well but thankfully we have a few more axes to play with. And that’s exactly what we’ll explore next.

Quantization Categories

Quantization can be divided based on :

Quantization Mapping: Affine vs Symmetric

Affine (asymmetric) quantization uses a non-zero zero-point \(z\), allowing the quantized range to better align with the floating-point distribution. It is commonly used with unsigned integer grids and provides flexibility by shifting where real zero is represented.

In contrast, symmetric quantization enforces \(z = 0\), using a range centered around zero. It is typically paired with signed integer grids and works well when the data distribution is approximately zero-centered.

Asymmetric vs Symmetric Quantization Symmetric vs Asymmertic Quantization. Source: Research Gate

Let’s see how this choice affects computation.

Recall:

$$ A_n = b_n + \sum_m (W_{n,m} \cdot x_m) $$

When \(W_{n,m}\) and \(x_m\) are quantized:

$$ W = s_w (W_{\text{int}} - z_w), \qquad x = s_x (x_{\text{int}} - z_x) $$

Substituing, we get:

MAC with quantization Source: A White Paper On Neural Network Quantization

The first term matches the symmetric case.
The third and fourth terms depend only on weights, scales, and offsets, so they can be precomputed and folded into the bias at negligible cost.

The second term, however, depends on the input \(x\), meaning it must be computed at inference time, adding latency and power overhead.

Hence, a common strategy is asymmetric activations + symmetric weights, which avoids this data-dependent cost.

How Quantization Is Applied (Quantization Granularity)

Per Tensor

One entire tensor shares a single scale (\(s\)) and zero-point (\(z\)).

Effective bits per value:

Assuming the scale and zero-point are stored in 16 bits each, the effective number of bits per value is:

$$ \text{effective bits} = b + \frac{16 + 16}{N} $$

where:

  • \(b\) = quantized bit-width (e.g., 8)
  • \(N\) = total number of elements in the tensor

Example:

For \(N = 1024\) and \(b = 8\):

$$ \text{effective bits} = 8 + \frac{32}{1024} = 8.03125 $$

So, 8-bit quantization requires slightly more than 8 bits per value once the scale and zero-point are included.

Per Channel

Each channel has its own scale (\(s\)) and zero-point (\(z\)).

Assume a matrix of shape \((C, K)\), where each row (or column) is a channel.

Effective bits per value:

$$ \text{effective bits} = b + \frac{C \cdot (16 + 16)}{N} $$

where:

  • \(C\) = number of channels
  • \(N = C \cdot K\) = total number of elements

Example:

For a matrix with \(C = 64\) channels and \(K = 16\) values per channel:

$$ N = 64 \cdot 16 = 1024 $$

$$ \text{effective bits} = 8 + \frac{64 \cdot 32}{1024} = 10 $$

Per Block

A block of values shares a single scale (\(s\)) and zero-point (\(z\)).

Effective bits per value:

$$ \text{effective bits} = b + \frac{16 + 16}{B} $$

where:

  • \(b\) = quantized bit-width (e.g., 8)
  • \(B\) = block size

Example:

For a block size of \(B = 64\) and \(b = 8\):

$$ \text{effective bits} = 8 + \frac{32}{64} = 8.5 $$

In general, finer-grained schemes (more parameters) yield better accuracy but introduce additional storage and compute overhead. Per-channel quantization generally offers a good tradeoff for weights, while per-block quantization is applied to particularly sensitive weights. However, per-channel quantization for activations is hardware-inefficient and the reason becomes clear once you expand the MAC computation.

With per-channel quantization, weights and activations each have their own per-channel scale vectors:

$$ \mathbf{s}_w = [s_{w_1}, s_{w_2}, \ldots, s_{w_n}], \qquad \mathbf{s}_x = [s_{x_1}, s_{x_2}, \ldots, s_{x_m}] $$

Substituting the dequantized values into the accumulator equation:

$$ A_n = b_n + \sum_{m} \left( W_{n,m} \cdot s_{w_n} \right) \cdot \left( x_m \cdot s_{x_m} \right) $$

$$ A_n = b_n + s_{w_n} \sum_{m} W_{n,m} \cdot x_m \cdot s_{x_m} $$

Notice that \(s_{w_n}\) does not depend on \(m\), so it can be factored out of the summation and applied as a single scalar multiply after accumulation. This is cheap and hardware-friendly. \(s_{x_m}\), however, depends on \(m\) which means it cannot be factored out. Instead, each product \(W_{n,m} \cdot x_m\) must be rescaled by a different \(s_{x_m}\) before accumulation. This is why per-channel quantization is standard for weights but avoided for activations.

Based on how activations are quantized:

Since weights are always known before inference they can be quantized offline, however, activations depend on the input to the model, and there are two ways of quantizing them.

In static quantization, the min and max ranges of activations are calculated using a small subset of the training data called calibration dataset which typically contains around 300-500 samples.

In dynamic quantization, the min-max ranges are calculated on the fly during inference. This is useful in situations where the model execution time is dominated by loading weights from memory rather than computing the matrix multiplications.

For integer quantization, static quantization is most common.

Based on when it is applied: During Training or Inference?

Quantization aware training (QAT) simlutes inference-time quantization duering training by using quantized weights and activations in the forward pass, while using full precision weights in the backward pass. The idea is to emulate the inference time quantization error by using quantized values in the forward pass, and allowing the backward pass to update the full-precision weights such that they become more robust to quantization. This approach leads to better accuracy preservation as the model learns to adapt to the precision loss during training.

An illustration of forward and backward pass for QAT
Quantization Aware Training. Source: Quantization and Deployment of Deep Neural Networks on Microcontrollers

Unlike quantization aware training, where the model learns to adjust to lower precision during training, post-training quantization (PTQ) directly applies this reduction in bit width after the model has been trained. While it may not offer the same level of accuracy preservation as quantization aware training, it is widely used in practice since it doesn’t require retraining the model.

In this series, we will primarily focus on post-training quantization (PTQ) techniques.

Enough simulation — how do integer models actually run on the MAC?

Meme

The weights and activations are loaded in low precision (e.g., int8 × int8, or int8 × int16 on some hardware). Since inputs are quantized, we move less data. Each cycle performs the multiply (e.g., 8×8 or 8×16), and the results are accumulated in higher precision, typically int32.

So does the next layer receive 32-bit values? Not quite. We requantize the accumulator back to low precision before passing it on.

MAC with dequantize op
Source: A White Paper On Neural Network Quantization

Requantization

Recall that on the MAC, the accumulator computes:

$$ A_n = b_n + \sum_{m} C_{n,m} = b_n + \sum_{m} W_{n,m} \cdot x_m $$

When weights and activations are quantized, the real values are recovered via dequantization:

$$ W_{n,m} = s_w \left( W_{\text{int}_{n,m}} - z_w \right), \qquad x_m = s_x \left( x_{\text{int}_m} - z_x \right) $$

Substituting into the accumulator:

$$ A_n = b_n + \sum_{m} s_w \left( W_{\text{int}_{n,m}} - z_w \right) \cdot s_x \left( x_{\text{int}_m} - z_x \right) $$

$$ A_n = b_n + s_w s_x \sum_{m} \left( W_{\text{int}_{n,m}} - z_w \right)\left( x_{\text{int}_m} - z_x \right) $$

The hardware computes the inner sum entirely in integer arithmetic, accumulating into a high-precision int32 register:

$$ A_{\text{int}_n} = \sum_{m} \left( W_{\text{int}_{n,m}} - z_w \right)\left( x_{\text{int}_m} - z_x \right) $$

So the real-valued accumulator output is simply:

$$ A_n \approx s_w s_x \cdot A_{\text{int}_n} $$

Now, this output needs to be passed to the next layer which expects quantized inputs with its own scale \(s_y\) and zero-point \(z_y\). So we need to quantize \(A_n\):

$$ y_{\text{int}_n} = \left\lfloor \frac{A_n}{s_y} \right\rceil + z_y = \left\lfloor \frac{s_w s_x}{s_y} \cdot A_{\text{int}_n} \right\rceil + z_y $$

Defining the requantization scale:

$$ M = \frac{s_w s_x}{s_y} $$

The full requantization step becomes:

$$ y_{\text{int}_n} = \mathrm{clamp}\!\left( \left\lfloor M \cdot A_{\text{int}_n} \right\rceil + z_y,\ y_{\text{int}}^{\min},\ y_{\text{int}}^{\max} \right) $$

This is the only floating-point operation in the pipeline - multiplying the int32 accumulator by \(M\) to rescale it into the next layer’s quantization range.

In practice, \(M\) is implemented using fixed-point arithmetic (an integer multiply followed by a bit shift), keeping the entire pipeline in integer arithmetic - see Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference , Section 2.2, for the full derivation.

Conclusion

That was a lot to cover and, if you made it this far, well done! We looked at why quantization matters (memory, energy, throughput), how it works mathematically (the quantization and dequantization pipeline, rounding vs clipping tradeoff), the key design choices (symmetric vs asymmetric, per-tensor vs per-channel vs per-block, static vs dynamic, PTQ vs QAT), and why certain combinations like symmetric weights with asymmetric activations, or per-tensor activation quantization are preferred in practice.

All of this assumes the weight and activation distributions are reasonably well-behaved. In the next post, we’ll see why transformers break that assumption and why that makes quantizing them surprisingly hard.

References & Further Reading