Worked examples — Processing-in-memory (PIM)
The scenario matrix
Every PIM sizing question boils down to two quantities you must compute from a workload:
- Arithmetic intensity — compute ops per byte moved. Here is the number of arithmetic operations and is the number of bytes moved across the bus. Low = bandwidth-bound = PIM loves it. (See Roofline Model.)
- Bandwidth speedup ceiling — how much more internal bandwidth PIM unlocks vs the external bus. Here is the external bus bandwidth (bytes/second on the wire between memory and CPU), is the number of memory banks that can compute in parallel, and is the bandwidth inside one bank. Their product is the total internal bandwidth PIM harvests.
The matrix below enumerates every case class this topic can throw at you. The seven examples afterward each cover one row (or the extreme of a row), and are labelled by cell.
| Case | Case class | What's extreme about it | Example |
|---|---|---|---|
| A | Low intensity (streaming) | → PIM wins big | Ex 1 |
| B | High intensity (compute-bound) | → PIM barely helps | Ex 2 |
| C | Break-even | exactly at the roofline ridge | Ex 3 |
| D | Degenerate: zero compute | (pure copy) → | Ex 4 |
| E | Limiting: infinite banks | , Amdahl's cap bites | Ex 5 |
| F | Analog PUM accuracy | crossbar with quantization error | Ex 6 |
| G | Word problem / exam twist | energy budget, not time | Ex 7 |
| H | Degenerate: no data | → undefined | Ex 8 |

Example 1 — Case A: streaming, very low intensity
- Count compute ops. One add per element → . Why this step? Intensity is ops-per-byte; we need the op count first.
- Count bytes moved. Read
b, readc, writea= 3 accesses × 4 bytes × = bytes. Why? The bus cost is set by every byte crossing it, reads and writes alike. - Compute intensity. ops/byte. Why? This tiny number lands us far left of the red ridge → bandwidth-bound.
- Internal bandwidth. GB/s. Why? Each bank computes in parallel; their internal bandwidths add (DRAM Organization (banks, rows)).
- Speedup ceiling. . Why not ? Because per-bank bandwidth () is below the bus (); the win is the ratio of aggregate internal to external, not the bank count.
Verify: Units: ✓ dimensionless speedup ✓. Sanity: correctly flags a bandwidth-bound streaming kernel — exactly what PIM targets. is modest but real. Matches parent's Worked Example 2.
Example 2 — Case B: dense matmul, high intensity (PIM barely helps)
- Ops. A dense matmul does FLOPs (a multiply + an add per inner term): . Why? output cells, each an -length dot product = MACs = flops.
- Bytes (naïve, no reuse counted). Three matrices: bytes. Why? We move A, B, and C once each — the minimum traffic.
- Intensity. ops/byte. Why? This is far right of the red ridge → compute-bound.
- Verdict. Each byte feeds ~167 ops → the CPU/GPU keeps its ALUs busy and caches hide the memory. PIM's data-movement win is nearly invisible here.
Verify: ✓ opposite extreme of Ex 1 (). Ratio — the two workloads sit ~3.3 decades apart on the roofline, correctly on opposite sides of the ridge. See Neural Network Accelerators: they tile matmul precisely to raise reuse and stay compute-bound.
Example 3 — Case C: the break-even ridge
- Write both time terms. Move time , compute time . Balance means they're equal. Why? The Roofline Model ridge is the exact crossover where the two costs match.
- Set equal and solve. . Why? Dividing through by turns raw counts into the intensity we can look up. Recall = peak compute rate (GFLOP/s), = bus bandwidth (GB/s).
- Plug numbers. ops/byte. Why? Below → bus-bound (PIM helps). Above → compute-bound (PIM meh).
- PIM's effect. PIM raises the effective bandwidth from to , which moves the ridge right to . Workloads that were just barely compute-bound can fall back into the bandwidth-bound zone — but only ones near the ridge.
Verify: Units: ✓. . Ex 1 () is bandwidth-bound ✓; Ex 2 () is compute-bound ✓ — both classifications are consistent with this single ridge value.
Example 4 — Case D: degenerate, zero compute (pure copy)
- Compute ops. A copy does no arithmetic: . Why? This is the degenerate corner of the intensity axis.
- Bytes. Read
b, writea= 2 accesses × 4 bytes × = bytes. Why? Movement still happens — that's the whole point of the case. - Intensity. ops/byte — the extreme left edge of the roofline, below even Ex 1. Why? Zero over a nonzero number is a clean ; the ratio is well-defined (contrast: if were also , it'd be , undefined — that corner is drilled in Ex 8).
- PIM verdict. Maximally bandwidth-bound. But note: PIM computes, and here there's nothing to compute. Near-memory copy (in-DRAM row-clone / RowClone) still helps by never crossing the bus; a compute-style crossbar does not.
Verify: ✓, the true floor of the intensity axis (, ordering intact). Degenerate-input handled: gives a defined ; the corner is Ex 8.
Example 5 — Case E: limiting behaviour, infinite banks meets Amdahl
- Bandwidth ceiling grows without bound. as . Why? Nothing in the pure-bandwidth model caps it — that's the trap. Note is the ceiling of the parallel (bandwidth-bound) part only; it is exactly the "" we feed into Amdahl next.
- Bring in Amdahl's Law. Overall speedup , where is the serial fraction and is the same bandwidth ceiling from step 1 — the only part Amdahl lets us accelerate. Why this tool? Amdahl answers exactly "what does the program speedup approach when one part goes infinitely fast?" — the right question here, not raw bandwidth.
- Take the limit. As , , so speedup . Why? The serial can't be sped up; it dominates once everything else is free.
- Interpretation. Even with perfect infinite-bank PIM, this workload caps at . The bus/serial residue is the wall.
Verify: ✓. Sanity: with a smaller serial fraction the cap would rise to — monotonic and correct. Limiting case handled: gives a finite , not infinity. Parent's warning "always sanity-check against Amdahl" ✓.
Example 6 — Case F: analog PUM crossbar accuracy
- Ideal current per cell (Ohm's law). : , , (mA). Why Ohm's law? Each crosspoint is literally a resistor; is the exact device physics.
- Sum the row (Kirchhoff's current law). mA. Why? Currents merging on one wire add — that summation is the dot product .
- Apply drift. First cell drifts : mS → its current mA. New sum mA. Why? Real conductances wander; this is why PUM is approximate, not exact.
- Relative error. . Why less than ? The drift hits one term contributing half the total, and the other terms are unaffected — errors dilute across the sum.
Verify: Ideal mA, drifted mA, error ✓. Confirms parent's mistake-callout: crossbars are approximate, suited to error-tolerant nets, not exact finance.
Example 7 — Case G: word problem / exam twist (energy, not time)
- Baseline energy. Move: pJ. Compute: pJ. Total pJ. Why split them? PIM only attacks the move term; separating shows how dominant it is.
- Confirm movement dominates. vs → movement is compute here. Why check? If compute dominated, saving movement would be pointless — this is the energy version of the intensity test.
- PIM energy. Only of bytes move: pJ. Compute unchanged: pJ. Total pJ. Why compute unchanged? PIM doesn't make the arithmetic cheaper — it removes the trips.
- Saving. . Why so large? Because movement was compute, cutting of movement cuts ~ of total energy.
Verify: pJ, pJ, saving ✓. Units: pJ throughout ✓. Confirms the parent's core energy thesis: attack movement, not the ALU.
Example 8 — Case H: the fully degenerate corner, no data at all
- Write the ratio. . Why? This is the last unvisited corner of the intensity axis — both numerator and denominator vanish.
- Classify the ratio. is indeterminate — mathematically undefined, not and not . Why does this matter? Unlike Ex 4 (clean because only ), here you cannot place the workload anywhere on the roofline — there is no workload.
- Physical reading. No bytes move → the bus was never the bottleneck; no ops run → there is nothing to accelerate. Both time terms and are , so total time regardless of architecture.
- PIM verdict. PIM neither helps nor hurts: speedup is too. In practice a runtime guards against empty inputs before ever asking "should I PIM this?" — the intensity test is undefined and must be skipped.
Verify: undefined ✓ (contrast Ex 4's defined ). Both cost terms and ✓, so runtime is on any machine — the correct limiting reading of an empty kernel.
Active Recall
Pure copy has so (Case D)
Infinite banks cap at because of
The drift gave total error because
Empty input gives undefined (Case H)
memcpy where only so is a clean