A dense layer is memory-bound until the batch is large
complexity▲▲△For a single dense layer of shape in fp32, derive the arithmetic intensity — FLOPs performed per byte of memory moved — as a function of the batch size . Tabulate it for from 1 to 1024, and say what the numbers imply about running an MLP one example at a time.
Hint
Count the traffic honestly: the weights are read once per batch, the inputs and outputs scale with . Then take the limit in .
Solution
The two counts. A batch of rows through performs multiply–adds, or FLOPs. The bytes moved, at 4 bytes each, are the weights once plus the input and output rows:
The table, at :
| FLOP/byte | weights as a share of traffic | |
|---|---|---|
| 1 | ||
| 2 | ||
| 8 | ||
| 32 | ||
| 128 | ||
| 256 | ||
| 1024 |
The limit. Divide through by :
so the intensity rises towards and never passes it. Small is the regime where the denominator is dominated by , and the intensity is approximately .
What it implies. At the layer performs one multiply–add per weight and does half a FLOP per byte moved. Accelerators reach their peak arithmetic rate only above roughly FLOP/byte, so a batch of one leaves the machine idle by more than two orders of magnitude: the time is spent reading weights, not multiplying. The layer is memory-bound, and making the matrix bigger does not help, since the weights grow as fast as the arithmetic.
Three consequences.
Batching is not only a statistical decision. I.4 discusses the batch as a variance choice; this is the other axis, and at the hardware cost is paid whatever the statistics say.
FLOPs are a poor proxy for time. Two models with the same FLOP count differ by a factor of hundreds if one runs at and the other at . I.5.B04’s caution has its arithmetic here.
Single-example inference is the hard case. Serving one request at a time is exactly the memory-bound regime, which is why inference systems batch requests across users, and why the same problem returns for the KV cache in Book IV.