1%{ @file cache_miss_rmf.m
2 % @brief Computes miss rates
using the refined mean field (RMF) method
4 % @author LINE Development Team
8 % @brief Computes cache miss rates
for RANDOM(m) replacement via refined mean field
11 % This function computes global, per-user, and per-item miss rates
for
12 % multi-list caches with RANDOM(m) replacement
using the DDPP mean field
13 % approximation with 1/N correction (refined mean field). The cache
14 % occupancy
is computed from
the aggregate request stream; per-user miss
15 % rates weight
the per-item miss probabilities by each user
's rates.
18 % N. Gast, "Expected Values Estimated via Mean-Field Approximation are
19 % 1/N-Accurate", Proc. ACM Meas. Anal. Comput. Syst., 2017.
23 % [M, MU, MI, pi0] = cache_miss_rmf(gamma, m, lambda)
28 % <tr><th>Name<th>Description
29 % <tr><td>gamma<td>Item access factors (used for sizing only)
30 % <tr><td>m<td>Cache capacity vector
31 % <tr><td>lambda<td>Arrival rates per user per item per list
36 % <tr><th>Name<th>Description
37 % <tr><td>M<td>Global miss rate
38 % <tr><td>MU<td>Per-user miss rate
39 % <tr><td>MI<td>Per-item miss rate
40 % <tr><td>pi0<td>Per-item miss probability
43function [M,MU,MI,pi0,tout,pi0_t,MU_t,xtraj] = cache_miss_rmf(gamma, m, lambda, tspan, x0init) %#ok<INUSL>
44% Optional TSPAN = [t0, t1] and initial occupancy X0INIT request the
45% transient mean-field trajectory: integrating the same drift F(x) that
46% RMF_FIXED_POINT drives to steady state, over the finite window. Returns
47% the time grid TOUT, the per-item list-0 occupancy PI0_T (n_items x nt)
48% and the per-user miss-rate trajectory MU_T (u x nt). Omitting TSPAN
49% preserves the original steady-state-only contract.
50if nargin < 4, tspan = []; end
51if nargin < 5, x0init = []; end
53n_items = size(lambda,2);
57% aggregate per-item request rates over users
58lam_i = zeros(1, n_items);
61 row(~isfinite(row)) = 0;
64p = lam_i / sum(lam_i);
66model_dim = n_items * (h + 1);
68% Build initial state: first m(1) items in list 1, next m(2) in
69% list 2, etc.; remaining items outside cache (list 0)
70x0 = zeros(model_dim, 1);
74 obj_idx = obj_idx + 1;
76 x0(rmf_index(obj_idx, k, n_items)) = 1.0;
80for i = (obj_idx + 1):n_items
81 x0(rmf_index(i, 0, n_items)) = 1.0;
84% Mean field fixed point, then 1/N refinement when computable. The
85% refinement solves a reduced Jacobian/Lyapunov system that turns singular
86% for small or non-hyperbolic fixed points; MATLAB signals this with a
87% (non-error) warning and returns non-finite entries rather than throwing,
88% so a bare try/catch does not catch it. Accept
the 1/N correction only
89% when it
is finite, otherwise keep
the plain mean-field fixed point.
90xss = rmf_fixed_point(x0, p, m, n_items, h, model_dim);
91% The refinement's reduced linear system
is expected to be singular for
92% small/non-hyperbolic fixed points; silence only that specific warning here
93% since
the non-finite result
is detected and rejected below.
94ws1 = warning('off', 'MATLAB:singularMatrix');
95ws2 = warning('off', 'MATLAB:nearlySingularMatrix');
96restoreWarn = onCleanup(@() warning([ws1 ws2]));
98 [pi_mf, V] = rmf_expansion_steady_state(x0, p, m, n_items, h, model_dim);
99 xref = pi_mf + V / n_items;
100 if all(isfinite(xref))
104 % Fall back to plain mean field
108% Per-item miss probability (occupancy of list 0), clipped to [0,1]
109pi0 = zeros(n_items, 1);
111 pi0(i) = max(0, min(1, xss(rmf_index(i, 0, n_items))));
118 row(~isfinite(row)) = 0;
123% Transient mean-field trajectory (optional): integrate
the drift over
the
124% requested window from
the supplied (or default) initial occupancy. XTRAJ
is
125%
the full DDPP occupancy trajectory (model_dim x nt), used to carry
the cache
126% mean occupancy across environment switches.
127tout = []; pi0_t = []; MU_t = []; xtraj = [];
134 ode_func = @(t, x) rmf_drift(x, p, m, n_items, h, model_dim);
135 odeopt = odeset('AbsTol', 1e-10, 'RelTol', 1e-8);
136 [tout, xtraj] = ode15s(ode_func, tspan, x0init, odeopt);
137 xtraj = xtraj'; % model_dim x nt
139 pi0_t = zeros(n_items, nt);
141 pi0_t(i,:) = max(0, min(1, xtraj(rmf_index(i, 0, n_items), :)));
146 row(~isfinite(row)) = 0;
147 MU_t(v,:) = row * pi0_t;
152function idx = rmf_index(i, k, n_items)
153% RMF_INDEX Map (item i, list k) to flat state index
154% i: item index (1-based)
155% k: list index (0 = outside cache, 1..h = cache lists)
156% n_items: total number of items
157idx = i + k * n_items;
160function hr = rmf_hit_rate(x, p, list_number, n_items)
161% RMF_HIT_RATE Compute hit rate contribution from a specific list
162% hr = sum_i p(i) * x(index(i, list_number))
165 hr = hr + p(i) * x(rmf_index(i, list_number, n_items));
169function dX = rmf_drift(x, p, m, n_items, h, model_dim)
170% RMF_DRIFT Compute mean field drift F(x) for RANDOM(m) replacement
172% dx[i,k]/dt = -p(i)*x[i,k] + hitRate[k]*x[i,k+1]/m(k) (promotion from k to k+1)
173% dx[i,k+1]/dt = p(i)*x[i,k] - hitRate[k]*x[i,k+1]/m(k)
175hit_rates = zeros(1, h + 1);
177 hit_rates(k + 1) = rmf_hit_rate(x, p, k, n_items);
180dX = zeros(model_dim, 1);
183 flow = p(i) * x(rmf_index(i, k, n_items)) ...
184 - hit_rates(k + 1) * x(rmf_index(i, k + 1, n_items)) / m(k + 1);
185 dX(rmf_index(i, k, n_items)) = dX(rmf_index(i, k, n_items)) - flow;
186 dX(rmf_index(i, k + 1, n_items)) = dX(rmf_index(i, k + 1, n_items)) + flow;
191function Fp = rmf_jacobian(x, p, m, n_items, h, model_dim)
192% RMF_JACOBIAN Compute Jacobian dF/dx at state x
194hit_rates = zeros(1, h + 1);
196 hit_rates(k + 1) = rmf_hit_rate(x, p, k, n_items);
199Fp = zeros(model_dim, model_dim);
202 ik = rmf_index(i, k, n_items);
203 ik1 = rmf_index(i, k + 1, n_items);
206 Fp(ik, ik) = Fp(ik, ik) - p(i);
207 Fp(ik1, ik) = Fp(ik1, ik) + p(i);
208 Fp(ik, ik1) = Fp(ik, ik1) + hit_rates(k + 1) / m(k + 1);
209 Fp(ik1, ik1) = Fp(ik1, ik1) - hit_rates(k + 1) / m(k + 1);
211 % Indirect terms via hit rate dependence on x(j,k)
213 jk = rmf_index(j, k, n_items);
214 jk1 = rmf_index(j, k + 1, n_items);
215 Fp(ik, jk1) = Fp(ik, jk1) - p(i) * x(ik) / m(k + 1);
216 Fp(ik1, jk1) = Fp(ik1, jk1) + p(i) * x(ik) / m(k + 1);
217 Fp(ik, jk) = Fp(ik, jk) + p(j) * x(ik1) / m(k + 1);
218 Fp(ik1, jk) = Fp(ik1, jk) - p(j) * x(ik1) / m(k + 1);
224function Fpp = rmf_hessian(~, p, m, n_items, h, model_dim)
225% RMF_HESSIAN Compute Hessian d^2F/dx^2 (constant for this quadratic drift)
227Fpp = zeros(model_dim, model_dim, model_dim);
230 ik = rmf_index(i, k, n_items);
231 ik1 = rmf_index(i, k + 1, n_items);
234 jk = rmf_index(j, k, n_items);
235 jk1 = rmf_index(j, k + 1, n_items);
236 % d^2 F[ik] / (d x[jk] d x[ik1])
237 Fpp(ik, jk, ik1) = Fpp(ik, jk, ik1) + p(j) / m(k + 1);
238 Fpp(ik, ik1, jk) = Fpp(ik, ik1, jk) + p(j) / m(k + 1);
239 % d^2 F[ik] / (d x[jk1] d x[ik])
240 Fpp(ik, jk1, ik) = Fpp(ik, jk1, ik) - p(i) / m(k + 1);
241 Fpp(ik, ik, jk1) = Fpp(ik, ik, jk1) - p(i) / m(k + 1);
243 Fpp(ik1, jk, ik1) = Fpp(ik1, jk, ik1) - p(j) / m(k + 1);
244 Fpp(ik1, ik1, jk) = Fpp(ik1, ik1, jk) - p(j) / m(k + 1);
245 Fpp(ik1, jk1, ik) = Fpp(ik1, jk1, ik) + p(i) / m(k + 1);
246 Fpp(ik1, ik, jk1) = Fpp(ik1, ik, jk1) + p(i) / m(k + 1);
253function Q = rmf_noise_matrix(x, p, m, n_items, h, model_dim)
254% RMF_NOISE_MATRIX Compute noise intensity matrix Q(x) for
the DDPP
256% Q[a,b] = sum_ell ell[a]*ell[b]*beta_ell(x)
257% Each transition swaps items i and j across lists k and k+1.
259Q = zeros(model_dim, model_dim);
260signs = [-1, 1, 1, -1];
264 rate = p(i) * x(rmf_index(i, k, n_items)) ...
265 * x(rmf_index(j, k + 1, n_items)) / m(k + 1);
266 indices = [rmf_index(i, k, n_items), ...
267 rmf_index(j, k, n_items), ...
268 rmf_index(i, k + 1, n_items), ...
269 rmf_index(j, k + 1, n_items)];
272 Q(indices(ia), indices(ib)) = Q(indices(ia), indices(ib)) ...
273 + rate * signs(ia) * signs(ib);
281function pi = rmf_fixed_point(x0, p, m, n_items, h, model_dim)
282% RMF_FIXED_POINT Compute mean field fixed point by ODE integration
284% Integrates dx/dt = F(x) until steady state using ode15s.
287ode_func = @(t, x) rmf_drift(x, p, m, n_items, h, model_dim);
288odeopt = odeset('AbsTol', 1e-10, 'RelTol', 1e-8);
289[~, xvec] = ode15s(ode_func, [0, tmax], x0, odeopt);
290%[~, xvec] = lsoda_solve(ode_func, [0, tmax], x0, odeopt);
294function [C, Cinv, rk] = rmf_dimension_reduction(Fp, n_items, h, model_dim)
295% RMF_DIMENSION_REDUCTION Compute change-of-basis for singular Jacobian
297% The Jacobian
is singular because item populations are conserved
298% (sum over lists for each item = 1). Returns matrices to project
299% onto
the non-singular subspace.
303C = zeros(model_dim, model_dim);
306 for i = 1:(n_items - 1)
308 C(d, rmf_index(i, l_idx, n_items)) = 1.0;
313C((rk + 1):model_dim, :) = U(:, (rk + 1):model_dim)';
317function [pi, V] = rmf_expansion_steady_state(x0, p, m, n_items, h, model_dim)
318% RMF_EXPANSION_STEADY_STATE Compute refined mean field steady-state expansion
320% Computes
the mean field fixed point pi and
the 1/N correction V
321% using
the Lyapunov equation approach with dimension reduction.
323% The refined approximation for a system of N items
is:
324% E[X] ~ pi + V/N + O(1/N^2)
326pi = rmf_fixed_point(x0, p, m, n_items, h, model_dim);
328Fp = rmf_jacobian(pi, p, m, n_items, h, model_dim);
329Fpp = rmf_hessian(pi, p, m, n_items, h, model_dim);
330Q = rmf_noise_matrix(pi, p, m, n_items, h, model_dim);
332% Dimension reduction: project onto non-singular subspace
333[C, Cinv, rk] = rmf_dimension_reduction(Fp, n_items, h, model_dim);
335Fp_r = (C * Fp * Cinv);
336Fp_r = Fp_r(1:rk, 1:rk);
338% Reduce Hessian: Fpp_r(a,b,c) = sum_{i,j,k} C(a,i)*Fpp(i,j,k)*Cinv(j,b)*Cinv(k,c)
339% First contraction: tmp1(a,j,k) = sum_i C(a,i)*Fpp(i,j,k)
340tmp1 = zeros(model_dim, model_dim, model_dim);
344 tmp1(a, j, k) = C(a, :) * Fpp(:, j, k);
348% Second contraction: tmp2(a,b,k) = sum_j tmp1(a,j,k)*Cinv(j,b)
349tmp2 = zeros(rk, rk, model_dim);
353 tmp2(a, b, k) = tmp1(a, :, k) * Cinv(:, b);
357% Third contraction: Fpp_r(a,b,c) = sum_k tmp2(a,b,k)*Cinv(k,c)
358Fpp_r = zeros(rk, rk, rk);
361 Fpp_r(a, b, :) = reshape(tmp2(a, b, :), 1, []) * Cinv(:, 1:rk);
366Q_r = Q_r(1:rk, 1:rk);
368% Solve Lyapunov equation: Fp_r * W_r + W_r * Fp_r' + Q_r = 0
369W_r = lyap(Fp_r, Q_r);
371% First-order correction: V_r = -Fp_r \ (C_r / 2)
372% where C_r = sum_{b,c} Fpp_r(:,b,c) * W_r(b,c)
377 C_r(a) = C_r(a) + Fpp_r(a, b, c) * W_r(b, c);
381V_r = -Fp_r \ (C_r / 2.0);
383% Expand back to full dimension
384V = Cinv(:, 1:rk) * V_r;