LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
da_cacheqn.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2026, QORE Lab, Imperial College London
3 * All rights reserved.
4 */
5#ifndef LINE_API_DA_DA_CACHEQN_H
6#define LINE_API_DA_DA_CACHEQN_H
7
8/**
9 * @file
10 * @ingroup api_da
11 * Decomposition-aggregation driver for integrated cache-queueing models, a port
12 * of matlab/src/api/da/da_cacheqn.m.
13 *
14 * Alternates between (i) solving each cache in isolation given the current
15 * per-class arrival rates and (ii) solving the surrounding queueing network with
16 * every cache replaced by a class switch that routes according to the current
17 * hit/miss probabilities, until the cache arrival rates reach a fixed point
18 * (da_fpi under the 1-norm). The cache node is RELABELLED to a ClassSwitch but
19 * stays stateful, so it remains a retained node of the stochastic complement --
20 * exactly as the reference does. The per-sweep routing rewrite goes straight
21 * into `rtnodes`, after which `da_recompute_visits_from_rtnodes` rebuilds `rt`
22 * and the visits with the chains held fixed.
23 *
24 * ARITHMETIC: the miss solve (cache_mva / cache_miss_fpi) and the network solve
25 * decide the achievable T; the driver itself is field arithmetic. The tolerance
26 * loop is inexact by construction whatever the backend.
27 */
28
29#include <cstddef>
30#include <limits>
31#include <functional>
32#include <vector>
33
40#include "line/api/da/da_fpi.h"
43#include "line/util/error.h"
44#include "line/util/matrix.h"
45
46namespace line {
47namespace da {
48
49/** The converged isolated-cache inputs, kept for per-item occupancy reporting. */
50template <class T>
52 std::vector<Matrix<T> > gamma; ///< per cache: (n x h)
53 std::vector<std::vector<int> > itemcap; ///< per cache
54 std::vector<std::vector<Matrix<T> > > lambda_cache;///< per cache: (u) of n x (h+1)
55 std::vector<std::vector<std::vector<Matrix<T> > > > Rcost;
56 std::vector<lang::ReplacementStrategy> strat;
57 std::vector<std::vector<int> > itemsize; ///< per cache, EMPTY without item sizes
58 std::vector<std::vector<int> > costcap; ///< per cache, EMPTY without cost caps
59};
60
61template <class T>
64 Matrix<T> hitprob; ///< (ncaches x nclasses)
65 Matrix<T> missprob; ///< (ncaches x nclasses)
66 int iter = 0;
68};
69
70/**
71 * Per-item occupancy of every cache from the CONVERGED access factors.
72 *
73 * This is the EMBEDDED (per-request) law: the stationary law of the cache-content
74 * chain seen at request instants, which coincides with the time-stationary one
75 * only under PASTA. SolverCTMC reports the time-weighted counterpart instead.
76 *
77 * RR/FIFO past 10 items is NaN, not the fixed point's marginals: the exact
78 * recursion is what makes these a distribution, and an approximation of it is
79 * not one. SolverMVA and SolverNC read the same law off their own fixed points,
80 * so it is derived here rather than in either analyzer.
81 *
82 * @return one (n x h+1) matrix per cache, column 0 the miss probability; an
83 * EMPTY matrix where the cache carries no access factors
84 */
85template <class T>
86std::vector<Matrix<T> > da_cacheqn_itemprob(const CacheqnInfo<T>& info) {
87 std::vector<Matrix<T> > out(info.gamma.size(), Matrix<T>());
88 for (std::size_t ci = 0; ci < info.gamma.size(); ++ci) {
89 if (info.gamma[ci].rows() == 0) continue;
90 const std::size_t ni = info.gamma[ci].rows();
91 const std::size_t hi = info.itemcap[ci].size();
92 if (info.strat[ci] == lang::ReplacementStrategy::LRU) {
93 std::vector<T> mT(hi);
94 for (std::size_t l = 0; l < hi; ++l)
95 mT[l] = num_traits<T>::from_int(info.itemcap[ci][l]);
96 out[ci] = cache::cache_ttl_lrua(
97 info.lambda_cache[ci], info.Rcost[ci], mT,
99 } else if (ni > 10) {
100 out[ci] = Matrix<T>(ni, hi + 1,
102 std::numeric_limits<double>::quiet_NaN()));
103 } else {
104 out[ci] = cache::cache_prob_erec(info.gamma[ci], info.itemcap[ci], info.itemsize[ci],
105 info.costcap[ci]);
106 }
107 }
108 return out;
109}
110
111/**
112 * @brief Decomposition-aggregation driver for integrated cache-queueing
113 * models, a port of matlab/src/api/da/da_cacheqn.m.
114 *
115 * @param sn the model struct, taken by value and mutated (caches relabelled)
116 * @param exact true selects the exact isolated-cache miss, false the
117 * approximation; consulted only when `missfun` is empty
118 * @param opt iteration controls (iter_max, tol)
119 * @param netfun solves the surrounding queueing network on the mutated struct;
120 * its MvaSolution.X is read as the per-class system throughput
121 * @param missfun THE ISOLATED-CACHE MISS ALGORITHM, as the reference's `missfun`
122 * handle. Empty selects the MVA pair (`cache_mva` /
123 * `cache_miss_fpi`), which is what SolverMVA passes; SolverNC
124 * supplies `cache_prob_erec` / `cache_miss_spm` instead. The
125 * reference has always taken a handle here -- an earlier version
126 * of this port collapsed it to `exact`, which hardcoded one
127 * solver's pair into a driver both solvers share.
128 *
129 * THE FOURTH ARGUMENT IS THE CACHE ITSELF, as the reference's
130 * `missfun(gamma, m, lambda_cache, ch)` passes it. Without it a
131 * handle cannot see the replacement strategy or the access graph
132 * of the cache it is being asked about, so a model with two
133 * caches under different policies would be solved by whichever
134 * one the handle was written for. SolverFLD reads exactly those
135 * two fields; SolverMVA and SolverNC ignore the argument.
136 */
137template <class T>
139 const std::function<mva::MvaSolution<T>(const qn::NetworkStruct<T>&)>&
140 netfun,
141 const std::function<std::vector<T>(const Matrix<T>&,
142 const std::vector<int>&,
143 const std::vector<Matrix<T> >&,
144 const qn::CacheParam<T>&,
145 const std::vector<int>&)>&
146 missfun = nullptr) {
147 const T zero = num_traits<T>::from_int(0), one = num_traits<T>::from_int(1);
148 const std::size_t I = sn.nodes.size(), K = sn.nclasses;
149
150 std::vector<std::size_t> caches; // 0-based node indices
151 for (std::size_t nd = 0; nd < I; ++nd)
152 if (sn.nodes[nd].nodetype == qn::NodeType::Cache) caches.push_back(nd);
153 const std::size_t ncaches = caches.size();
154
155 // The fixed point isolates each cache under Poisson reads; a cache fed by another cache's hit/miss
156 // classes sees the upstream miss stream, which that isolation does not model.
157 for (std::size_t a : caches) {
158 const qn::CacheParam<T>& ca = sn.nodeparam.at(a + 1);
159 for (std::size_t b : caches) {
160 if (a == b) continue;
161 for (std::size_t r = 0; r < ca.hitclass.size(); ++r) {
162 const std::size_t outs[2] = {ca.hitclass[r], r < ca.missclass.size() ? ca.missclass[r] : 0};
163 for (std::size_t o : outs) {
164 if (o == 0) continue; // 1-based, 0 = none
165 for (std::size_t s = 0; s < K; ++s)
166 if (sn.rtnodes(a * K + (o - 1), b * K + s) > zero)
167 throw UnsupportedError(ErrorKind{"Cache"},
168 "The cache fixed point does not support a cache network in which cache " +
169 sn.nodes[a].name + " feeds cache " + sn.nodes[b].name + "; use CTMC, SSA or LDES.");
170 }
171 }
172 }
173 }
174
175 // connmatrix from the ORIGINAL node routing, before the cache rows are
176 // rewritten: node ind connects to jnd if any class routes ind -> jnd.
177 std::vector<std::vector<bool> > conn(I, std::vector<bool>(I, false));
178 for (std::size_t a = 0; a < I; ++a)
179 for (std::size_t b = 0; b < I; ++b) {
180 if (a == b) continue; // the cache's read self-switch is not a downstream
181 for (std::size_t r = 0; r < K && !conn[a][b]; ++r)
182 for (std::size_t s = 0; s < K && !conn[a][b]; ++s)
183 if (sn.rtnodes(a * K + r, b * K + s) > zero) conn[a][b] = true;
184 }
185
186 CacheqnResult<T> outr;
187 outr.hitprob = Matrix<T>(ncaches, K, zero);
188 outr.missprob = Matrix<T>(ncaches, K, zero);
189 outr.info.gamma.resize(ncaches);
190 outr.info.itemcap.resize(ncaches);
191 outr.info.lambda_cache.resize(ncaches);
192 outr.info.Rcost.resize(ncaches);
193 outr.info.strat.resize(ncaches);
194 outr.info.itemsize.resize(ncaches);
195 outr.info.costcap.resize(ncaches);
196
197 // seed cache arrival rates and relabel the caches as class switches
198 std::vector<T> lambda0(K, zero);
199 for (std::size_t ci = 0; ci < ncaches; ++ci) {
200 const qn::CacheParam<T>& ch = sn.nodeparam.at(caches[ci] + 1);
201 for (std::size_t r = 0; r < ch.hitclass.size(); ++r)
202 if (ch.hitclass[r] != 0)
203 lambda0[r] = num_traits<T>::from_double(0.5); // deterministic seed (no rand)
204 sn.nodes[caches[ci]].nodetype = qn::NodeType::ClassSwitch;
205 }
206
207 da::FpiOptions fopt;
208 fopt.iter_max = opt.iter_max;
209 fopt.iter_tol = opt.tol;
210 // The reference stops on the 1-norm of the increment; this da_fpi uses the
211 // max-norm. Both converge to the same fixed point (the point is what the
212 // metrics read), so only the iteration count can differ, which is not
213 // compared.
214
215 mva::MvaSolution<T> lastres;
216 auto sweep = [&](const std::vector<T>& x,
217 std::size_t) -> std::pair<std::vector<T>, std::vector<T> > {
218 std::vector<T> lambda = x;
219 for (std::size_t ci = 0; ci < ncaches; ++ci) {
220 const std::size_t ind = caches[ci];
221 const qn::CacheParam<T>& ch = sn.nodeparam.at(ind + 1);
222
224 dch.itemcap = ch.itemcap;
225 dch.nitems = ch.nitems;
226 dch.pread = ch.pread;
227 dch.accost = ch.accost;
228 const da::CacheIsolateResult<T> iso = da::da_cache_isolate(dch, lambda);
229 outr.info.gamma[ci] = iso.gamma;
230 outr.info.itemcap[ci] = ch.itemcap;
231 outr.info.lambda_cache[ci] = iso.lambda_cache;
232 outr.info.Rcost[ci] = iso.Rcost;
233 outr.info.strat[ci] = ch.replacestrat;
234 outr.info.itemsize[ci] = ch.itemsize;
235 outr.info.costcap[ci] = ch.costcap;
236
237 // per-class miss rate of the isolated cache
238 std::vector<T> missrate(K, zero);
239 if (missfun) {
240 const std::vector<T> mr = missfun(iso.gamma, ch.itemcap, iso.lambda_cache, ch, iso.parent);
241 for (std::size_t v = 0; v < mr.size() && v < K; ++v) missrate[v] = mr[v];
242 } else if (exact) {
243 // cache_mva is the exact law of RR/FIFO only, as in solver_mva_cache_analyzer
246 throw UnsupportedError(ErrorKind{"Cache"},
247 "MVA does not support exact solution of the specified cache replacement policy.");
249 const std::size_t n = cm.pij.rows(), h = cm.pij.cols();
250 std::vector<T> pmiss(n, zero);
251 for (std::size_t k = 0; k < n; ++k) {
252 T s = zero;
253 for (std::size_t l = 0; l < h; ++l) s = T(s + cm.pij(k, l));
254 pmiss[k] = T(one - s);
255 }
256 for (std::size_t v = 0; v < iso.lambda_cache.size() && v < K; ++v) {
257 T acc = zero;
258 for (std::size_t k = 0; k < n; ++k)
259 acc = T(acc + iso.lambda_cache[v](k, 0) * pmiss[k]);
260 missrate[v] = acc;
261 }
262 } else {
263 // cache_miss_fpi wants lambda as the (u x n) first-list slice.
264 const std::size_t u = iso.lambda_cache.size();
265 const std::size_t n = ch.nitems;
266 Matrix<T> lam_un(u, n, zero);
267 for (std::size_t v = 0; v < u; ++v)
268 for (std::size_t k = 0; k < n; ++k) lam_un(v, k) = iso.lambda_cache[v](k, 0);
272 cache::cache_miss_fpi(iso.gamma, ch.itemcap, lam_un);
273 for (std::size_t v = 0; v < mr.MU.size() && v < K; ++v) missrate[v] = mr.MU[v];
274 } else {
275 // LRU and h-LRU take the TTL approximations of solver_mva_cache_analyzer
276 Matrix<T> pij;
278 std::vector<T> mT(ch.itemcap.size());
279 for (std::size_t l = 0; l < ch.itemcap.size(); ++l)
280 mT[l] = num_traits<T>::from_int(ch.itemcap[l]);
282 iso.lambda_cache, iso.Rcost, mT,
285 pij = cache::cache_ttl_hlru(lam_un, ch.itemcap);
286 } else {
287 throw UnsupportedError(ErrorKind{"Cache"},
288 "MVA does not support approximate solution of the specified cache replacement policy.");
289 }
290 for (std::size_t v = 0; v < u && v < K; ++v) {
291 T acc = zero;
292 for (std::size_t k = 0; k < n; ++k)
293 acc = T(acc + lam_un(v, k) * pij(k, 0));
294 missrate[v] = acc;
295 }
296 }
297 }
298
299 for (std::size_t r = 0; r < K; ++r) {
300 if (lambda[r] > zero) {
301 outr.missprob(ci, r) = T(missrate[r] / lambda[r]);
302 outr.hitprob(ci, r) = T(one - outr.missprob(ci, r));
303 } else {
304 outr.missprob(ci, r) = zero;
305 outr.hitprob(ci, r) = zero;
306 }
307 }
308
309 // rewrite the cache-as-classswitch routing into rtnodes: send the
310 // hit/miss mass to EVERY connected node, exactly as the reference. The
311 // row over-sums when there is more than one downstream node; the
312 // reference does not normalise it, and the surplus is absorbed by the
313 // pass-through classes (which each queue routes onward to its own
314 // successors) at zero residence.
315 for (std::size_t r = 0; r < ch.hitclass.size(); ++r) {
316 if (ch.hitclass[r] == 0) continue; // class r does not read this cache
317 const std::size_t hc = ch.hitclass[r] - 1, mc = ch.missclass[r] - 1;
318 for (std::size_t col = 0; col < I * K; ++col) sn.rtnodes(ind * K + r, col) = zero;
319 for (std::size_t jnd = 0; jnd < I; ++jnd) {
320 if (!conn[ind][jnd]) continue;
321 sn.rtnodes(ind * K + r, jnd * K + hc) = outr.hitprob(ci, r);
322 sn.rtnodes(ind * K + r, jnd * K + mc) = outr.missprob(ci, r);
323 }
324 }
325 }
326 // The cache switch forces classes onto nodes that never carried them in
327 // the base model, where they have no onward routing. The reference's
328 // refresh routes every class at a node to that node's physical
329 // successors (same class); reproduce it for the classes left unrouted, so
330 // a pass-through class exits instead of dead-ending (which would zero its
331 // throughput and unbalance the served classes).
332 for (std::size_t i = 0; i < I; ++i) {
333 if (sn.nodes[i].nodetype == qn::NodeType::Cache ||
334 sn.nodes[i].nodetype == qn::NodeType::ClassSwitch)
335 continue; // caches (relabelled) carry their explicit switch row
336 std::size_t nsucc = 0;
337 for (std::size_t j = 0; j < I; ++j)
338 if (conn[i][j]) ++nsucc;
339 if (nsucc == 0) continue; // a Sink has no successors
340 const T share = T(one / num_traits<T>::from_int(long(nsucc)));
341 for (std::size_t s = 0; s < K; ++s) {
342 T rowsum = zero;
343 for (std::size_t col = 0; col < I * K; ++col) rowsum = T(rowsum + sn.rtnodes(i * K + s, col));
344 if (rowsum > zero) continue; // already routed
345 for (std::size_t j = 0; j < I; ++j)
346 if (conn[i][j]) sn.rtnodes(i * K + s, j * K + s) = share;
347 }
348 }
349 sn.da_recompute_visits_from_rtnodes();
350
351 lastres = netfun(sn);
352
353 // node visits summed over chains
354 Matrix<T> nv(I, K, zero);
355 for (std::size_t c = 0; c < sn.nchains; ++c)
356 for (std::size_t a = 0; a < I; ++a)
357 for (std::size_t r = 0; r < K; ++r) nv(a, r) = T(nv(a, r) + sn.nodevisits[c](a, r));
358
359 // update cache arrival rates from the network throughputs
360 for (std::size_t ci = 0; ci < ncaches; ++ci) {
361 const std::size_t ind = caches[ci];
362 const qn::CacheParam<T>& ch = sn.nodeparam.at(ind + 1);
363 for (std::size_t r = 0; r < ch.hitclass.size(); ++r) {
364 if (ch.hitclass[r] == 0) continue;
365 // chain of class r
366 std::size_t c = sn.nchains;
367 for (std::size_t cc = 0; cc < sn.nchains; ++cc)
368 if (sn.chains[cc][r]) { c = cc; break; }
369 if (c == sn.nchains) continue;
370 T xsum = zero;
371 for (std::size_t k : sn.inchain[c]) xsum = T(xsum + lastres.X[k - 1]);
372 const std::size_t rstat = sn.classes[r].refstat; // 1-based station
373 const std::size_t refnode = sn.station_to_node[rstat - 1] - 1; // 0-based
374 const std::size_t refcls =
375 (sn.refclass[c] > 0) ? sn.refclass[c] - 1 : r; // 0-based
376 const T denom = nv(refnode, refcls);
377 if (denom > zero) lambda[r] = T(xsum * nv(ind, r) / denom);
378 }
379 }
380 return std::make_pair(lambda, x);
381 };
382
383 const da::FpiResult<T> fp = da::da_fpi<T>(sweep, lambda0, fopt);
384 outr.iter = static_cast<int>(fp.iterations);
385 outr.res = lastres;
386 return outr;
387}
388
389} // namespace da
390} // namespace line
391
392#endif // LINE_API_DA_DA_CACHEQN_H
Cache miss rates from the fixed-point multipliers.
Exact mean value analysis of a multi-list cache.
Exact per-item hit and miss probabilities of a multi-list cache.
TTL (characteristic-time) approximation of an h-LRU / LRU(m) cache.
TTL (characteristic-time) approximation of an LRU cache whose lists form an arbitrary access graph.
UnsupportedError(const std::string &what)
Definition error.h:119
A network plus its refreshed NetworkStruct.
Isolated-cache input construction for the decomposition methods.
Damped fixed-point iteration, the shared driver of the decomposition algorithms.
The exception types the port throws.
Dense matrix and non-owning view.
The option and result types every MVA analyzer shares.
CacheMvaResult< T > cache_mva(const Matrix< T > &gamma, const std::vector< int > &m)
Exact mean value analysis of a multi-list cache.
Definition cache_mva.h:66
CacheMissResult< T > cache_miss_fpi(const Matrix< T > &gamma, const std::vector< int > &m, const Matrix< T > &lambda)
Cache miss rates from the fixed-point multipliers.
Matrix< T > cache_prob_erec(const Matrix< T > &gamma, const std::vector< int > &m, const std::vector< int > &sigma, const std::vector< int > &k)
Per-item hit and miss probabilities under per-list storage cost caps, pi_ij = m_j gamma(i,...
Matrix< T > cache_ttl_hlru(const Matrix< T > &lambda, const std::vector< int > &m)
TTL (characteristic-time) approximation of an h-LRU / LRU(m) cache.
Matrix< T > cache_ttl_lrua(const Matrix< T > &lambda, const std::vector< Matrix< T > > &R, const std::vector< T > &m, const T &tol, unsigned maxswp=200)
TTL (characteristic-time) approximation of an LRU cache whose lists form an arbitrary access graph.
std::vector< Matrix< T > > da_cacheqn_itemprob(const CacheqnInfo< T > &info)
Per-item occupancy of every cache from the CONVERGED access factors.
Definition da_cacheqn.h:86
CacheqnResult< T > da_cacheqn(qn::NetworkStruct< T > sn, bool exact, const mva::MvaOptions &opt, const std::function< mva::MvaSolution< T >(const qn::NetworkStruct< T > &)> &netfun, const std::function< std::vector< T >(const Matrix< T > &, const std::vector< int > &, const std::vector< Matrix< T > > &, const qn::CacheParam< T > &, const std::vector< int > &)> &missfun=nullptr)
Decomposition-aggregation driver for integrated cache-queueing models, a port of matlab/src/api/da/da...
Definition da_cacheqn.h:138
FpiResult< T > da_fpi(const std::function< std::pair< std::vector< T >, std::vector< T > >(const std::vector< T > &, std::size_t)> &iterfun, const std::vector< T > &x0, const FpiOptions &options=FpiOptions())
Damped fixed-point iteration, the shared driver of the decomposition algorithms.
Definition da_fpi.h:102
CacheIsolateResult< T > da_cache_isolate(const CacheParam< T > &ch, const std::vector< T > &lambda)
Isolated-cache input construction for the decomposition methods.
@ HLRU
h-LRU / LRU(m): h lists, promote i -> i+1 on a hit
Definition lang_types.h:390
@ LRU
least recently used
Definition lang_types.h:389
@ FIFO
first in, first out
Definition lang_types.h:387
Conservation laws of a layered queueing network, enumerated from its structure.
Definition aoi_dist2ph.h:52
A queueing network and its refreshed NetworkStruct.
The <kind> part of a LINE:<category>:<kind> identifier (see _kb/17-error-vocabulary....
Definition error.h:37
Return value of cache_miss, mirroring [M,MU,MI,pi0].
Definition cache_miss.h:49
std::vector< T > MU
(u) per-user miss rate; empty when no lambda given
Definition cache_miss.h:51
Return value of cache_mva, mirroring [pi,pi0,pij,x,u,E].
Definition cache_mva.h:50
Return value of da_cache_isolate, mirroring [gamma,lambda_cache,Rcost].
std::vector< Matrix< T > > lambda_cache
(u) matrices of size n x (h+1)
Matrix< T > gamma
(n x h) access factors
std::vector< int > parent
list tree of cache_gamma_lp, as its parent
std::vector< std::vector< Matrix< T > > > Rcost
(u x n) of (h+1)x(h+1)
The fields of sn.nodeparam{cache} that da_cache_isolate reads.
std::vector< int > itemcap
(h) list capacities
std::vector< std::vector< Matrix< T > > > accost
(u) x (n) of (h+1)x(h+1), or empty
std::vector< std::vector< T > > pread
(u) x (n), empty row = NaN
The converged isolated-cache inputs, kept for per-item occupancy reporting.
Definition da_cacheqn.h:51
std::vector< std::vector< int > > itemsize
per cache, EMPTY without item sizes
Definition da_cacheqn.h:57
std::vector< std::vector< int > > costcap
per cache, EMPTY without cost caps
Definition da_cacheqn.h:58
std::vector< lang::ReplacementStrategy > strat
Definition da_cacheqn.h:56
std::vector< std::vector< std::vector< Matrix< T > > > > Rcost
Definition da_cacheqn.h:55
std::vector< Matrix< T > > gamma
per cache: (n x h)
Definition da_cacheqn.h:52
std::vector< std::vector< int > > itemcap
per cache
Definition da_cacheqn.h:53
std::vector< std::vector< Matrix< T > > > lambda_cache
per cache: (u) of n x (h+1)
Definition da_cacheqn.h:54
Matrix< T > missprob
(ncaches x nclasses)
Definition da_cacheqn.h:65
Matrix< T > hitprob
(ncaches x nclasses)
Definition da_cacheqn.h:64
CacheqnInfo< T > info
Definition da_cacheqn.h:67
mva::MvaSolution< T > res
Definition da_cacheqn.h:63
Options mirroring the fields MATLAB reads off the options struct.
Definition da_fpi.h:50
std::size_t iter_max
Definition da_fpi.h:51
std::size_t iterations
Definition da_fpi.h:88
static constexpr double FineTol
Definition lang_types.h:765
The options SolverMVA reads.
Definition mva_types.h:32
Class-level results, the [Q,U,R,T,C,X] of the MATLAB analyzers.
Definition mva_types.h:97
std::vector< T > X
Definition mva_types.h:99
The parameters of a Cache node, MATLAB's sn.nodeparam{ind} for a Cache.
std::vector< int > itemsize
Per-item storage cost (size) and per-list cap on the total cost of the resident items (ton21cache Sec...
std::vector< int > costcap
std::vector< std::vector< Matrix< T > > > accost
(u) x (n) of (h+1)x(h+1), or empty
std::vector< int > itemcap
std::vector< std::size_t > missclass
std::vector< std::size_t > hitclass
lang::ReplacementStrategy replacestrat
std::vector< std::vector< T > > pread
(u) x (n), empty row = NaN