DLRM L2-Pinning

Pushing the Performance Envelope of DNN-based Recommendation Systems Inference on GPUs — a software-only cross-kernel L2-residency technique for embedding rows, and why its own ablation makes it a small incremental slice.

MICRO 2024 arXiv:2410.22249 DLRM Inference L2 Pinning (PTX prefetch) A100 sm_80 Measured: PACE A100-80GB

Rishabh Jain, Vivek M. Bhasi, Adwait Jog, Anand Sivasubramaniam, Mahmut T. Kandemir, Chita R. Das

The Pennsylvania State University · University of Virginia

0. TL;DR — Why this paper is in our study

This page is part of the measurement study “Worth the Bytes?”, which argues that transient inter-kernel L2 reuse of activations in eager-mode LLM inference is worth less than 0.65% of step time. DLRM L2-pinning (L2P) is the most direct counterpart to that mechanism we could find in published systems work.

Same L2-residency phenomenon

A dedicated pre-kernel issues PTX prefetch.global.L2::evict_last on hot rows, then a stream sync, then the consumer reads those rows from L2 — the same cross-kernel L2-residency phenomenon, though the data semantics differ (persistent curated rows vs transient activations).

Its own ablation shrinks it

The paper's headline is up to 62% embedding-kernel / 48% e2e, but on the medium-reuse profile L2P adds only ~13.5% on top of register-prefetch+occupancy tuning.

A favorable case for L2

Reuse here is hand-engineered from a 60K hot-index list. We have no clean pin-charged net wall-clock result; the usable evidence is the L2-layer Nsight attribution (L2P ≈ RPF in steady state) plus the paper's own ~13.5%-incremental figure — consistent with our <0.65% bound.

Status of our numbers. Measured on PACE A100-80GB (sm_80), from-source PyTorch v2.1.0, jobs 9935235 (Nsight Compute L2 attribution) + 9942760 (cudaEvent latency ladder). Config: 12 tables × 500K rows × dim 128, batch 2048, pooling 150. Each result cell is tagged FACT, BOUND, ARTIFACT Static facts read directly from the artifact source are stated as confirmed.

1. Overview — the EmbeddingBag bottleneck

Deep-learning recommendation models (DLRM) interleave dense MLPs with very large embedding tables. At inference the dominant cost is the EmbeddingBag gather-reduce, a stream of irregular HBM reads that is latency-bound on the memory system.

1.1 Why now / the bad scenario

Embedding tables keep growing under tight SLAs. A single EmbeddingBag with pooling factor 150 over twelve 500K×128 fp32 tables issues hundreds of thousands of scattered row reads per batch, most of which miss every cache and go to HBM.

1.2 Baseline pain & the strawman

The working set far exceeds the A100's 40 MB L2, and shared memory is tiny. The repo even ships shared-memory and L1-prefetch variants that the paper does not adopt — evidence the SRAM route was tried and found wanting.

1.3 The obstacle & positioning

Popularity is skewed, so a small hot slice dominates lookups, but the baseline kernel cannot keep it resident across launches. The paper's three software-only techniques raise occupancy, hide latency in-kernel, and keep the hot slice warm in L2 across kernels — the last being our mechanism.

1.4 Contributions

  1. OptMT: occupancy/register-budget tuning via -maxrregcount 42.
  2. RPF: in-kernel register prefetch into lv0/lv1 — intra-kernel latency hiding, no cross-kernel state.
  3. L2P: a separate prefetch_pin_L2 kernel issuing prefetch.global.L2::evict_last on hot rows. This is the cross-kernel L2-residency mechanism our study measures.
62%
max embedding-kernel reduction (paper)
48%
max e2e reduction (paper)
~13.5%
L2P incremental, med reuse
60,000
hot rows / hot-index file

2. The L2-Pinning mechanism (annotated source)

L2P uses two kernels separated by a stream sync, inside one ATen op. A producer pins hot rows in L2; a consumer EmbeddingBag kernel reads them. The producer computes nothing — it only issues prefetch hints that change L2 replacement state.

2.1 The pin kernel (the producer)

From opt_designs/l2_pinning/EmbeddingBag.cu, lines 131–148. The evict_last hint biases the replacement policy toward later eviction (advisory, not guaranteed):

template <typename scalar_t, typename index_t>
__global__ void prefetch_pin_L2(const scalar_t *weight, int64_t featureSize,
                                int64_t weight_stride0,
                                int64_t const* d_hot_idx_vec, size_t pinning_size) {
    int Xidx = blockIdx.x * blockDim.x + threadIdx.x;
    int Yidx = threadIdx.y;
    int stride = gridDim.x * blockDim.x;
    if (Yidx < featureSize) {
        for (int i = Xidx; i < pinning_size; i += stride) {
            int64_t const lv_hot_idx = d_hot_idx_vec[i];        // a hot row id
            const scalar_t *weightFeat = weight + Yidx;
            // insert the L2 prefetch inline PTX code
            asm volatile (
                "prefetch.global.L2::evict_last [%0];" ::"l"(&weightFeat[lv_hot_idx * weight_stride0])
            :);
        }
    }
}

The hot-index list is read at runtime from DATASET_FILE_PATH (lines 447–471); each reuse profile points at its own 60,000-line hot-index file.

2.2 The pin→sync→consume sequence (and the timer)

The launch sequence, lines 494–517. The timer position is the single most important measurement detail on this page:

      } else {
        // cudaEventRecord(start, stream);              <-- commented out
        // reduce_L2_size<<<grid, 256, 0, stream>>>(d_dummy_vec, size_dummy);
        dim3 block_2 = dim3(2, 128);
        prefetch_pin_L2<scalar_t, index_t><<<grid, block_2, 0, stream>>>(   // PRODUCER: pin hot rows
            weight.const_data_ptr<scalar_t>(), featureSize, weight.stride(0),
            d_hot_idx_vec, pinning_size);
        cudaStreamSynchronize(stream);                // wait for the pin to finish
        // cudaEventRecord(stop, stream);               <-- commented out
        // cudaEventSynchronize(stop);                  <-- commented out

        cudaEventRecord(start, stream);              // <== TIMER STARTS HERE, AFTER THE PIN

        EmbeddingBag_updateOutputKernel_sum_mean<scalar_t, index_t><<<grid, block, 0, stream>>>(
            /* CONSUMER: reads the now-warm rows from L2 */ ... );

        cudaStreamSynchronize(stream);
        cudaEventRecord(stop, stream);
        cudaEventSynchronize(stop);
        cudaEventElapsedTime(&time, start, stop);   // time = CONSUMER ONLY
      }
Confirmed attribution fact (static, from source): The cudaEvent timer brackets only the consumer kernel; the pin kernel and its sync run before cudaEventRecord(start). The reported latency measures the L2-hit benefit while excluding the cost of producing it. A fair accounting must re-charge the pin time.

2.3 Why evict_last, and not a residency-control API

Ampere exposes two ways to bias L2 retention: the cudaStreamAttrValue access-policy-window (APW) API, or the per-instruction hint prefetch.global.L2::evict_last (warms a line and biases it toward later eviction). The core L2 trick is the per-instruction hint — finer-grained for a scattered hot-index list — but the measured wrapper also re-establishes an L2 access-policy window per batch (see §5) on top of re-reading the 60K hot-index file, so the artifact as run is PTX prefetch PLUS per-batch APW setup. The hint is advisory: demand traffic between pin and consume can evict hot rows before reuse, bounding the realized benefit.

2.4 Where the bytes live: the memory hierarchy

L2P targets the middle level — the device-wide L2 — so a later, independent kernel launch hits it:

SM / SRAMRegisters + shared memory (≤164 KB/SM). RPF stages here, intra-kernel only. Dies at kernel exit.
L2 (40 MB)Device-wide, persists across kernel launches. L2P pins hot rows here so the NEXT kernel hits L2 instead of HBM. This is our mechanism.
HBMMulti-GB tables (≈3 GB). Irregular row reads land here on an L2 miss — the traffic L2P removes.
The analogy — and the difference. In eager LLM inference, our study asks whether one kernel's output activation, left warm in L2, is hit by the next kernel before it is evicted. This is the same L2-residency hardware phenomenon, but with different producer/data semantics: DLRM L2P explicitly prefetches persistent, hand-curated hot embedding ROWS (weight-as-data), whereas eager-LLM activations are naturally-produced, written-once/read-once transients. That makes DLRM L2P a favorable case: the reuse is curated and persistent. That even this favorable regime adds essentially nothing at the L2 layer over register-prefetch in steady state corroborates the plausibility that the transient LLM activation-reuse effect is also small / conditional.

3. Repo analysis (artifact)

Each technique is a hand-written replacement of aten/src/ATen/native/cuda/EmbeddingBag.cu, recompiled into a from-source PyTorch v2.1.0. The optimization lives entirely in the CUDA kernel and the build flags.

reproduce_MICRO24_GPU_DLRM_inference/
opt_designs/
baseline/EmbeddingBag_timed.cu — reference kernel + cudaEvent timer (no maxrregcount)
l2_pinning/EmbeddingBag_timed.cu — prefetch_pin_L2 + consumer (OUR MECHANISM)
prefetching/EmbeddingBag_regpref.txt — RPF (register prefetch, lv0/lv1)
prefetching/EmbeddingBag_shmem.txt — tried, not headline (SRAM staging)
prefetching/EmbeddingBag_l1dpref_rolling.txt — tried, not headline (L1 prefetch)
combined/EmbeddingBag.cu — RPF + L2P + OptMT
datasets/
reuse_high|medium|low/table_500K.txt — access traces (3.93M / 0.43M / 0.38M lines)
random_500K.txt — ~4M random accesses (no reuse)
pinned_indices/rj_60K_{high,medium,low}_hot_indices.txt, rj_60K_random_indices.txt — 60,000 hot rows each
scripts/
load_emb.py — builds nn.EmbeddingBag, runs the forward, prints kernel latency
save_emb.py — regenerates test_500K_12.pt (gitignored, ~3 GB)
quick.sh / l2_quick.sh — profile loops (l2_quick.sh sets DATASET_FILE_PATH)
parser_Kernel_ET.py — averages kernel ET, drops the 1st (cold-miss) sample
env_files/
req.txt, pip_req_after_conda.txt, CMakeLists.txt — conda env + patched CMakeLists

3.1 Key kernels & symbols

Symbol File : lines Role
prefetch_pin_L2 l2_pinning/EmbeddingBag.cu : 131–148 Producer: emits the L2 prefetch PTX on each hot row.
EmbeddingBag_updateOutputKernel_sum_mean l2_pinning/EmbeddingBag.cu : 153 Consumer: the gather-reduce that benefits from warm L2.
reduce_L2_size l2_pinning/EmbeddingBag.cu : 116–127 Abandoned cache-thrash kernel (call site commented out).
lv0, lv1 prefetching/EmbeddingBag_regpref.txt : 141–188 RPF: register temporaries holding the prefetched value (intra-kernel).
cudaEventRecord(start) l2_pinning/EmbeddingBag.cu : 502 Timer start — AFTER the pin + sync. Consumer-only timing.

3.2 The four reuse profiles (confirmed counts)

The hotness sweep is what makes this artifact a stress test for our claim:

Profile Access trace (lines) Hot-index file (rows) Expected reuse
reuse_high3,933,21560,000High
reuse_medium429,95160,000Medium
reuse_low379,91060,000Low
random3,999,99960,000~None

3.3 The measurement harness

The Python side is thin: save_emb.py regenerates test_500K_12.pt (~3 GB), load_emb.py builds the EmbeddingBag and replays the trace, and the swapped CUDA kernel prints its own cudaEvent latency. parser_Kernel_ET.py averages over 12×12 launches and drops the first (cold-miss) sample — so the reported number already assumes a warm-ish cache, itself favorable to the reuse story.

4. The ablation ladder — how big is the L2 slice?

The page's whole point is to isolate the L2-residency contribution. The ladder builds five variants across four profiles; differencing adjacent rungs attributes each technique's marginal effect to a hardware cause. Only the non-pinning rungs (1–3) give a clean wall-clock difference; the L2P rungs (4–5) are artifact-dominated (§5), so the L2P attribution below is read NOT from §4.1 latency but from the Nsight L2 comparison (§7) plus the paper's ablation:

1
baseline
reference kernel
2
+ OptMT
occupancy
3
+ RPF
register prefetch
4
L2P
L2 pinning
5
combined
RPF+L2P+OptMT
Difference Attributed cause L2 reuse?
OptMT − baselineOccupancy / register budgetNO
RPF − OptMTIn-kernel register prefetchNO
L2P − OptMT via §7Cross-kernel L2 residency (read from §7, not §4.1 wall-clock)YES
combined − RPF via paperL2P increment over RPF (paper's ~13.5%, not our wall-clock)YES

4.1 Measured latency ladder (PACE A100, job 9942760)

Measured on PACE A100-80GB (jobs 9935235 + 9942760) Average batch latency (ms) per variant × profile

Variants 1–3 (no pinning path) are clean FACTs measured directly. Variants 4–5 (the L2P / combined pinning path) are dominated by a per-batch pinning-setup harness ARTIFACT and are NOT reported as L2P inference latency — see §5 and read the L2P contribution from the Nsight L2 attribution in §7.

Variant reuse_highreuse_mediumreuse_lowrandom
1 baseline3.616 fact4.6995.6805.875
2 + OptMT3.598 fact4.7195.6605.855
3 RPF + OptMT3.693 fact4.5135.0525.162
4 L2P + OptMT99.8 artifact102.45.901†102.5
5 RPF + L2P + OptMT97.5 artifact100.65.239†101.6

† The reuse_low cells in variants 4–5 are fast only because l2_quick.sh's hot-path list for that profile has a leading-space path bug → the hot-index file fails to open → pinning is silently skipped. Not a real L2P measurement either.

The clean rungs (1–3) show the validating shape: a strong reuse gradient (baseline hot 3.616 ms vs random 5.875 ms, ~1.6×, consistent with cache/hotness effects — the L2-specific share is attributed by §7, not this wall-clock), OptMT alone essentially flat (3.616 → 3.598 ms hot), and RPF+OptMT helping the cache-UNfriendly profiles (low −11%, random −12%) by hiding the DRAM latency L2 cannot when there is no reuse.

5. Why no pin-charged wall-clock is reported

Recall the confirmed fact from §2.2: the timer excludes the pin kernel. The repo's reported L2P speedup is therefore

$$\text{Speedup}_{\text{repo}} = \frac{T_{\text{baseline}}}{T_{\text{consumer}}^{\text{L2P}}}$$

which charges nothing for producing the warm L2 state. The pin kernel is not free: it touches all 60,000 hot rows in HBM, incurring real traffic and launch+sync overhead. In load_emb.py's harness that setup cost is re-paid every batch and cannot be cleanly separated into a one-time pin time — so rather than report a per-batch setup artifact as a net pin-charged wall-clock, we read the L2P contribution from the Nsight L2-layer attribution (§7) plus the paper's own ~13.5% ablation figure.

Honesty: the L2P / combined wall-clock is a harness ARTIFACT, not steady-state inference. The ~100 ms variant-4/5 wall-clock in §4.1 is NOT L2P inference latency: the wrapper (EmbeddingBag_timed.cu:447–460) re-reads the 60K hot-index file and re-establishes the L2 access-policy window on EVERY batch, so it measures per-call pinning SETUP, not steady-state inference. We therefore do NOT report a net pin-charged wall-clock speedup; we read the L2P contribution from the Nsight L2-layer attribution in §7 (L2P ≈ RPF in steady state) plus the paper's own ~13.5% figure.

artifact / not reported Why we do not report a net (pin-charged) wall-clock speedup

Across every profile the pin setup and the consumer launch cannot be cleanly separated into a one-time pin time plus an amortized steady-state consumer time, so there is no honest net (pin-charged) wall-clock speedup to tabulate — the values would all be per-batch setup artifacts.

In this harness the pin setup is re-paid every batch and cannot be separated into a one-time pin time, so any net wall-clock speedup here would be a setup-cost artifact. The L2-layer answer is in §7: at zero pressure, L2P adds essentially nothing over RPF (91.7% vs 91.8% L2 hit on hot).

6. Our reproduction on PACE (measured)

Reproduction status. Completed on PACE A100-80GB (sm_80). Job 9935235 captured the Nsight Compute L2-layer attribution (§7); job 9942760 captured the cudaEvent latency ladder (§4.1). The clean rungs and the ncu attribution are FACTs; the L2P wall-clock is a pinning-setup ARTIFACT we do not report (§5).

6.1 What we found (hypothesis & measured outcome)

We hypothesized the genuine cross-kernel L2-residency contribution is small and hotness-dependent; the measurements confirm both. (1) The L2 payoff is entirely hotness-dependent: ~92% hit / ~7.8 MB DRAM on reuse_high vs ~30% hit / ~145 MB DRAM (≈18× HBM) on random (FACT, §7). (2) L2P adds essentially nothing over RPF at the L2 layer in this no-polluter microbench (91.7% vs 91.8% hit) — consistent with the paper's ~13.5%-incremental figure (BOUND) and a parallel to our ‘dirty blob survives intact at zero pressure’ result.

6.2 Method — what we build and run

Single A100-80GB (sm_80), single-GPU, no TP. We keep the artifact's arch scope (TORCH_CUDA_ARCH_LIST="8.0", -maxrregcount 42); the repo has no H100 flags, so A100 is the only bit-faithful target. Each of the five variants is a separate from-source compile.

Build phase (per variant)

conda env ae_dlrm_gpu → clone PyTorch v2.1.0 → swap EmbeddingBag.cu → setup.py install. ~45–120 min each.

Run phase (Layer A: cudaEvent latency)

quick.sh / l2_quick.sh loop the 4 profiles; parser_Kernel_ET.py averages kernel ET, dropping the cold-miss 1st sample. Free attribution from existing prints.

Profile phase (Layer B: Nsight Compute)

ncu on RPF+OptMT vs L2P+OptMT, on reuse_high and random, --launch-count 4 (warm replay), metrics lts__t_sector_hit_rate.pct + dram__bytes_read.sum. Isolates the L2 signal (job 9935235).

6.3 Confirmed static facts (verifiable now)

These are read directly from the artifact and need no GPU run:

6.4 How to reproduce (commands)

After patching the hardcoded paths and regenerating the model:

# 0. regenerate the gitignored model (12 x 500K x 128 fp32, ~3 GB)
cd scripts && python save_emb.py

# 1. baseline: build with NO maxrregcount, then sweep the 4 profiles
cp opt_designs/baseline/EmbeddingBag_timed.cu \
   pytorch/aten/src/ATen/native/cuda/EmbeddingBag.cu
TORCH_CUDA_ARCH_LIST="8.0" python setup.py install
bash quick.sh > dummy; grep 'Latency of Embedding Bag kernel' dummy \
  | cut -d' ' -f6 | cut -d'm' -f1 > log; python parser_Kernel_ET.py

# 2-3. OptMT / RPF: rebuild with CMAKE_CUDA_FLAGS="-maxrregcount 42", rerun quick.sh

# 4. L2P: rebuild with l2_pinning .cu, run l2_quick.sh (it sets DATASET_FILE_PATH)
cp opt_designs/l2_pinning/EmbeddingBag_timed.cu \
   pytorch/aten/src/ATen/native/cuda/EmbeddingBag.cu
CMAKE_CUDA_FLAGS="-maxrregcount 42" python setup.py install
bash l2_quick.sh > dummy; ...   # 60K hot rows pinned per profile

# 5. combined (RPF+L2P+OptMT): rebuild with combined .cu, run l2_quick.sh
Hardware / build budget. A100-80GB, paid account. Five from-source compiles dominate the wall clock. If ncu is blocked (ERR_NVGPUCTRPERM), Layer B falls back to nsys durations while Layer A still works fully.

7. Nsight attribution — isolating the L2 signal

Layer A (latency diffs) tells us how big each rung is; Layer B (Nsight Compute) tells us why. The validating test is to profile RPF+OptMT vs. L2P+OptMT on the hot and the random profile — comparing register-prefetch (RPF+OptMT) against explicit pinning (L2P+OptMT) as two alternative consumer-side strategies, i.e. whether explicit L2 pinning beats register-prefetch at the L2 layer (baseline is NOT the Nsight comparand) — and watch two metrics: the L2 sector hit rate on the consumer kernel, and the HBM bytes read. If explicit L2P delivers more cross-kernel L2 reuse than register-prefetch, the hit rate must be higher and HBM reads lower on hot; and the hotness sweep itself (hot vs random) shows whether the L2 payoff exists at all.

7.1 The metrics that separate L2 from everything else

ncu metric What it isolates
lts__t_sector_hit_rate.pctL2 hit rate — the headline reuse signal.
lts__t_sectors_lookup_hit.sum / ...miss.sumAbsolute L2 hit/miss sectors.
dram__bytes_read.sumHBM read bytes — the traffic L2 reuse removes.
smsp__inst_executed_op_shared_ld.sumShared-memory loads — ~0, rules out SRAM.
sm__warps_active.avg.pct_of_peak_sustained_activeOccupancy — isolates OptMT.
launch__registers_per_threadConfirms maxrregcount 42 (= 42 for OptMT/RPF).
gpu__time_duration.sumPer-kernel time — cross-checks kernel durations; the L2P contribution itself is read from the L2-layer metrics, not from a wall-clock pin time.

7.2 The L2-attribution result (measured, job 9935235)

Measured on PACE A100-80GB (job 9935235) Consumer-kernel L2 hit rate & HBM reads (lts__t_sector_hit_rate.pct, dram__bytes_read.sum), first→steady over 4 launches

Variant × profile L2 hit% first→steady DRAM read first→steady
reuse_high · RPF+OptMT74.0 → ~91.8 fact27.5 → ~7.8 MB
reuse_high · L2P+OptMT74.6 → ~91.7 fact27.5 → ~7.8 MB
random · RPF+OptMT30.4 → 30.5 fact144.6 → 144.9 MB
random · L2P+OptMT30.4 → 30.6 fact144.8 → 144.9 MB

Raw: results/dlrml2pin_a100-80_9935235/ncu/*.csv. Warm replay across 4 launches; the first→steady columns show the warming trend.

Finding 1 (FACT): L2 payoff is entirely hotness-dependent

Hot rows reach ~92% L2 hit / ~7.8 MB DRAM; random sits at ~30% hit / ~145 MB DRAM (≈18× more HBM). L2 reuse buys nothing without reuse — the embedding-table analogue of our activation bound.

Finding 2 (FACT + BOUND): L2P ≈ RPF at the L2 layer

L2P adds essentially nothing over RPF at the L2 layer here: 91.7 vs 91.8% hit, DRAM essentially equal. Consistent with the paper's ~13.5%-incremental figure and a parallel to our ‘dirty blob survives at zero pressure’ result — pinning matters only under cross-kernel pollution the tight loop does not impose.

Caveat (under-statement). L2P's benefit is plausibly UNDERSTATED here because no intervening polluter evicts the hot rows between pin and consumer — the regime where evict_last would help. We report the L2-layer attribution as measured and lean on the paper's ~13.5% figure (BOUND) for the polluted regime.

This contrast — ~92% steady-state L2 hit on reuse_high collapsing to ~30% with ≈18× HBM traffic on random, and L2P ≈ RPF at the L2 layer — validates the thesis: the inter-kernel L2 benefit is a property of the access pattern, not the kernel pair, and explicit pinning adds nothing over register-prefetch without cross-kernel pollution.

7b. Claims vs. implementation (honest reading)

Because the techniques live entirely in one swappable CUDA file, we can check each paper claim against the source. The status column reflects what the code does, cross-checked against our PACE A100 measurements where relevant.

Paper claim Status Code evidence
L2P pins hot rows in L2 via a hardware prefetch hint. YES prefetch.global.L2::evict_last inline PTX (line 144).
L2P is a software-only, drop-in EmbeddingBag replacement. YES One file swapped into aten/.../EmbeddingBag.cu + a build flag; no driver/HW changes.
Reported kernel latency reflects the L2P benefit. PARTIAL True for the consumer, but the timer EXCLUDES the pin kernel + sync (lines 497–502).
L2P delivers up to 62% / 48% reduction. PARTIAL Best-case, consumer-only. Our ncu shows the L2 payoff is entirely hotness-dependent (~92% hot vs ~30% random) and L2P ≈ RPF at the L2 layer (91.7% vs 91.8%); the headline reflects warm best-case reuse, not the L2P increment alone.
L2P benefit vanishes without reuse. YES Confirmed by our ncu hot-vs-random test: pinning a random index list gives only ~30% L2 hit / ~145 MB DRAM (no benefit) vs ~92% / ~7.8 MB for hot rows.
RPF hides latency by prefetching (distinct from L2P). YES Stages into registers lv0/lv1 intra-kernel (regpref.txt:141–188); not L2 reuse.

Strengths of the artifact

  • The mechanism is explicit and isolatable: the PTX prefetch line is the core consumer-side hint (the producer side still re-establishes a per-batch L2 access-policy window, §5).
  • A clean ablation ladder differences out occupancy and register-prefetch.
  • A built-in hotness sweep gives the vanish test for free.
  • cudaEvent prints enable Layer-A attribution without a profiler.

Limitations / caveats

  • Headline timer excludes the pin kernel — overstates net value.
  • Reuse is hand-curated, not naturally transient.
  • Single-table microbenchmark; pin cost amortized over one launch.
  • A100-only build flags; H100 lacks a public recipe.
  • L2P/combined .cu omit explicit std-lib includes (build-fragile).

7c. Positioning — where L2 pinning sits among reuse techniques

Cross-kernel reuse can be attempted at every level of the GPU memory hierarchy. Placing L2P among the alternatives clarifies why it is the right object of study for an inter-kernel L2 claim.

Reuse level Crosses kernel? Representative Why bounded
Registers NO RPF (lv0/lv1) Dies at kernel exit.
Shared memory (SRAM) NO EmbeddingBag_shmem (tried) Tiny, per-block, re-staged each kernel.
L2 cache YES L2P (evict_last) — OUR FOCUS Persistent but small vs working set; pays only for re-demanded rows.
HBM / explicit staging YES Hot-row caching tables Software-managed; outside our L2 question.
Why L2P is the right probe. L2P is the only technique we found that explicitly targets L2, crosses a kernel boundary by design, and exposes a clean knob to dial reuse from maximal to zero — an almost ideal instrument to measure the ceiling of inter-kernel L2 value.

8. Tie-back to “Worth the Bytes?”

Our study expresses the L2-residency contribution as a share of step time. For DLRM L2P we read that contribution from the measured L2 layer rather than from a wall-clock pin time.

Because the L2P wall-clock is a pinning-setup artifact (§5), we do NOT compute a single pin-charged L2 share; we read the L2-layer contribution from the Nsight attribution (§7) and the paper's ~13.5% figure. The argument is corroborating, not a proof: L2P is among the most favorable cases imaginable, yet even here explicit pinning adds essentially nothing over RPF at the L2 layer (91.7% vs 91.8%) and the L2 payoff collapses with hotness (~92% → ~30% hit, ≈18× HBM on random). For naturally-transient eager-LLM activations this is consistent with a small, conditional contributor — supporting the plausibility of the <0.65% bound.

Measured on PACE A100-80GB (jobs 9935235 + 9942760) The numbers this page exists to produce

QuantityValue
Steady-state L2 hit, reuse_high~92% (RPF & L2P alike); ~7.8 MB DRAM/batch fact
Steady-state L2 hit, random~30%; ~145 MB DRAM/batch (≈18× HBM) fact
Measured L2-layer delta, L2P vs RPF≈0 (91.7% vs 91.8% hit) fact
Paper consumer-side L2P increment (med reuse)~13.5% (paper-reported; performance/latency, not an L2 hit-rate delta) bound
Net pin-charged wall-clock L2 sharenot reported (harness artifact, §5) artifact
vs the <0.65% eager-LLM boundcorroborates the bound's plausibility bound

8.1 What this page proves now vs. later

Already established (static)

  • L2P is literally cross-kernel L2-residency via evict_last PTX.
  • The repo's headline excludes the pin cost.
  • L2P increment over RPF+OptMT is small (~13.5% med) by the paper's own numbers.
  • Reuse is engineered, not transient — a favorable case.

Established by PACE runs (measured)

  • Clean baseline / OptMT / RPF ms (FACT): hot 3.616 → random 5.875 ms; RPF helps random −12%, low −11%.
  • L2 hit-rate & HBM-read, hot vs random (FACT): ~92% / ~7.8 MB vs ~30% / ~145 MB.
  • L2P ≈ RPF at the L2 layer (FACT): 91.7% vs 91.8% hit.
  • The L2P / combined wall-clock is a harness ARTIFACT — explicitly NOT reported as inference latency.

8.2 Bottom line

What we can now claim (measured). DLRM L2-pinning is a peer-reviewed instance of the same phenomenon, in one of its most favorable forms. Our PACE A100 Nsight runs show the L2 payoff is entirely hotness-dependent (~92% / ~7.8 MB hot vs ~30% / ~145 MB — ≈18× HBM — random) and L2P ≈ RPF at the L2 layer in steady state (91.7% vs 91.8%). We deliberately do not report a net pin-charged wall-clock speedup (the L2P wall-clock is a per-batch setup artifact). Net: a purpose-built cross-kernel L2-residency optimization only pays under row reuse and adds ~nothing over register-prefetch at the L2 layer — corroborating that the naturally-transient eager-LLM case is a small, conditional contributor, consistent with the <0.65% claim.