LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
solver_nc_cache.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_SOLVERS_NC_SOLVER_NC_CACHE_H
6#define LINE_SOLVERS_NC_SOLVER_NC_CACHE_H
7
8/**
9 * @file
10 * @ingroup line_solvers
11 * Port of `solver_nc_cache_analyzer.m`: the NON-REENTRANT cache, a model that
12 * is exactly a Source, a Cache and a Sink.
13 *
14 * WHAT THE ANALYZER ACTUALLY COMPUTES. There is no queueing here at all. Each
15 * class reads item k with probability `pread(v,k)`, the cache holds `itemcap`
16 * items per list, and the question is only which items are resident. The answer
17 * is a per-item occupancy `pij` -- column 0 the miss probability, column 1+j the
18 * probability that the item sits on list j -- from which the miss RATE follows
19 * by weighting with the read rates. The throughput table is then just the
20 * source rate split between each class's hit and miss classes.
21 *
22 * THREE ALGORITHMS, AND ONLY ONE OF THEM IS EXACT.
23 *
24 * exact `cache_prob_erec`, the exact recursion. REFUSED for any
25 * replacement policy outside the exchangeable (product-form)
26 * family: RR and FIFO have a product form, LRU / h-LRU / q-LRU /
27 * CLIMB do not, and the recursion would silently return the
28 * exchangeable answer for them.
29 * sampling `cache_miss_is` / `cache_prob_is`, importance sampling.
30 * default the SPM saddle point, which `spm` and `rayint` also name. With
31 * per-item storage costs it is `cache_spm_size`, the size-tilted
32 * expansion, reported as `spm.size`; without them it is
33 * `cache_miss_spm` / `cache_prob_spm`, reported as `spm`.
34 *
35 * WHY THE PER-LIST BREAKDOWN IS NaN OUTSIDE THE EXACT BRANCH, which is a
36 * deliberate refusal to report a number rather than an omission. Only the exact
37 * recursion produces a miss column and per-list columns from ONE consistent
38 * solution, so that the per-list rows sum to the aggregate hit. The approximate
39 * algorithms derive the miss and the per-list columns from different expansions
40 * and their breakdown does not form a distribution for more than one list.
41 *
42 * THE PER-ITEM TABLE IS ALWAYS TAKEN FROM THE EXACT RECURSION, even in the
43 * approximate branches: the cache is product-form, so the exact per-item table
44 * is available regardless of how the aggregate miss rate was obtained. It is
45 * skipped above 10 items, where the recursion stops being tractable.
46 */
47
48#include <algorithm>
49#include <cmath>
50#include <cstddef>
51#include <limits>
52#include <string>
53#include <vector>
54
56#include <sstream>
57
68#include "line/util/error.h"
69#include "line/util/matrix.h"
70
71namespace line {
72namespace nc {
73
74/** What the cache analyzer returns beyond the usual metric table. */
75template <class T>
78 Matrix<T> pij; ///< (n x h+1) per-item occupancy, column 0 = miss
79 Matrix<T> itemprob; ///< (n x h+1) the same from the EXACT recursion, NaN above 10 items
80 Matrix<T> hitproblist; ///< (u x h) access-weighted per-list hit probability, NaN if not exact
81 std::vector<T> missrate; ///< (u) per-class miss rate
82 /**
83 * (u) per-class miss and hit PROBABILITIES, `missrate` divided by the read
84 * class's arrival rate and its complement.
85 *
86 * Carried beside the rate because `getAvgCacheTable` reports a probability
87 * and the two differ by a factor no consumer downstream can recover: the
88 * arrival rate is the Source's and is gone by the time the table is built.
89 * NaN for a class with no read stream, which is not a hit ratio of zero.
90 */
91 std::vector<T> missprob, hitprob;
92 std::vector<T> listcost; ///< (h) mean storage cost held by each list, EMPTY without item sizes
93 /**
94 * Storage cost caps that block a promotion path, so that the exact
95 * recursion normalizes over MORE states than the cache can reach. The port
96 * has no warning channel, so this is a FLAG, like `SjnResult::capped`:
97 * a non-empty vector means cross-check the answer with SolverLDES.
98 */
99 std::vector<cache::CacheBlockedPair> costcap_blocked;
100 /** True when the requested method had no cost-capped counterpart and was switched. */
102};
103
104/** Miss rates of one isolated cache and what produced them; see `nc_cache_missrate`. */
105template <class T>
107 std::vector<T> missRate; ///< (u) miss rate of each user class
108 Matrix<T> pij; ///< (n x h+1) item occupancy of the chosen method, column 0 the miss one
109 std::string method;
110 bool exact = false; ///< pij came from the exact recursion
111 std::string warning;
112 std::vector<cache::CacheBlockedPair> costcap_blocked;
114};
115
116/**
117 * Miss rates of an isolated cache under `opt.method`, honouring the per-item
118 * storage costs and per-list cost caps of `ch`: exact recursion, size-tilted
119 * SPM, importance sampling, or the size-free SPM. Shared by the isolated
120 * analyzer and the cache-in-network fixed point, so both read item sizes the
121 * same way.
122 *
123 * @param parent the list tree of `cache_gamma_lp`
124 * @param lambda (u) of n x (h+1), the request rate of each class per item and list
125 */
126template <class T>
127NcCacheMiss<T> nc_cache_missrate(const Matrix<T>& gamma, const std::vector<int>& parent,
128 const std::vector<int>& m, std::size_t n,
129 const std::vector<Matrix<T>>& lambda,
130 const qn::CacheParam<T>& ch, const NcSolverOptions& opt) {
132 const T zero = num_traits<T>::from_int(0);
133 const std::size_t h = m.size();
134 const std::size_t u = lambda.size();
135 // lambda(:,:,1) as the (u x n) matrix the miss routines want.
136 Matrix<T> lam1(u, n, zero);
137 for (std::size_t v = 0; v < u; ++v)
138 for (std::size_t k = 0; k < n; ++k) lam1(v, k) = lambda[v](k, 0);
139
140 // Per-item storage costs and per-list cost caps (ton21cache Sec. IX).
141 const std::vector<int>& sigma = ch.itemsize;
142 const std::vector<int>& costcap = ch.costcap;
143 if (!costcap.empty()) {
144 if (sigma.empty())
145 throw InputError(
146 "solver_nc_cache_analyzer: storage cost caps require per-item sizes");
147 if (sigma.size() != n)
148 throw InputError(
149 "solver_nc_cache_analyzer: the item size vector must have one entry per item");
150 if (costcap.size() != h)
151 throw InputError(
152 "solver_nc_cache_analyzer: the cost cap vector must have one entry per cache "
153 "list");
155 cache::cache_cost_pathcheck(gamma, sigma, costcap, parent);
156 if (!r.costcap_blocked.empty()) {
157 // Carried on the solution's warning channel, not just as a flag:
158 // the reference warns here, and a flag no caller reads says nothing
159 std::ostringstream w;
160 w << "storage cost caps block the promotion path of item "
161 << (r.costcap_blocked[0].item + 1) << " into list "
162 << (r.costcap_blocked[0].list + 1) << " at list "
163 << (r.costcap_blocked[0].blocking_list + 1) << " (and "
164 << (r.costcap_blocked.size() - 1)
165 << " further pairs). The exact recursion normalizes over all size-feasible "
166 "states, which is then a strict superset of the states the cache can reach; "
167 "cross-check with SolverLDES.";
168 r.warning = w.str();
169 }
170 }
171
172 std::string cacheMethod = opt.method;
173 // 'rayint' is an alias of 'spm': on a cache both name the SPM saddle point,
174 // and the method name stays live for solver_nc_retrieval_analyzer's delayed-hit
175 // expansion.
176 if (cacheMethod == "rayint" || cacheMethod == "spm") cacheMethod = "default";
177 // The SPM family serves its size-tilted form (cache_spm_size) once the items
178 // carry storage costs. The saddle escapes to infinity at sum(m) = n, so the
179 // size-free saddle point takes over there rather than the exact recursion,
180 // which would refuse every replacement policy outside RR/FIFO.
181 long msum = 0;
182 for (std::size_t j = 0; j < h; ++j) msum += m[j];
183 const bool useSpmSize =
184 cacheMethod == "default" && !sigma.empty() && msum < static_cast<long>(n);
185 if (!costcap.empty() && !useSpmSize && cacheMethod != "exact" &&
186 cacheMethod != "sampling") {
187 // The size-free SPM and the mean-field methods have no cost-capped
188 // counterpart: the k - sigma_i e_j argument couples item sizes into the
189 // recursion graph, which only cache_spm_size and the exact path carry.
190 double lattice = static_cast<double>(n);
191 for (std::size_t j = 0; j < h; ++j)
192 lattice *= static_cast<double>(m[j] + 1) * static_cast<double>(costcap[j] + 1);
193 cacheMethod = (lattice <= 1e6) ? "exact" : "sampling";
195 std::ostringstream w;
196 w << "method '" << opt.method << "' does not support storage cost caps; using '"
197 << cacheMethod << "' instead.";
198 r.warning = r.warning.empty() ? w.str() : r.warning + " " + w.str();
199 }
200
201 std::vector<T>& missRate = r.missRate;
202 missRate.assign(u, zero);
203 if (cacheMethod == "exact") {
204 // cache_prob_erec is exact only for the exchangeable family.
207 throw UnsupportedError(ErrorKind{"Cache"},
208 "solver_nc_cache_analyzer: NC does not support the exact solution of this "
209 "cache replacement policy -- only RR and FIFO are exchangeable, and a "
210 "recency-based policy (LRU, h-LRU, q-LRU, CLIMB) would silently receive the "
211 "exchangeable answer. Use the default (approximate) method or SolverCTMC");
212 r.pij = cache::cache_prob_erec(gamma, m, sigma, costcap);
213 for (std::size_t v = 0; v < u; ++v) {
214 T acc = zero;
215 for (std::size_t k = 0; k < n; ++k) acc += T(lambda[v](k, 0) * r.pij(k, 0));
216 missRate[v] = acc;
217 }
218 r.exact = true;
219 r.method = "exact";
220 } else if (useSpmSize) {
221 // Size-tilted SPM: a 2h Newton solve whose cost does not grow with the
222 // (m,k) lattice the exact recursion walks. O(1/n), so it wants room
223 // between the occupancies and n.
224 std::vector<int> raycap = costcap;
225 if (raycap.empty()) {
226 // Sizes but no caps: cap each list at the dearest load it can hold,
227 // which is exactly slack, so the cost coordinate leaves the saddle
228 // and the expansion degenerates to the size-free one.
229 std::vector<int> srt = sigma;
230 std::sort(srt.begin(), srt.end(), std::greater<int>());
231 raycap.assign(h, 0);
232 for (std::size_t j = 0; j < h; ++j) {
233 int top = 0;
234 for (int a = 0; a < m[j]; ++a) top += srt[static_cast<std::size_t>(a)];
235 raycap[j] = top;
236 }
237 }
239 cache::cache_spm_size<T>(gamma, m, sigma, raycap);
240 r.pij = ray.pij;
241 for (std::size_t v = 0; v < u; ++v) {
242 T acc = zero;
243 for (std::size_t k = 0; k < n; ++k) acc += T(lambda[v](k, 0) * r.pij(k, 0));
244 missRate[v] = acc;
245 }
246 r.method = "spm.size";
247 } else if (cacheMethod == "sampling") {
249 cache::cache_miss_is(gamma, m, lam1, opt.samples, opt.seed, sigma, costcap);
250 missRate = mi.MU;
251 r.pij = cache::cache_prob_is(gamma, m, opt.samples, opt.seed, sigma, costcap);
252 r.method = "sampling";
253 } else {
254 // Size-free SPM, the default/spm/rayint branch with no item sizes.
255 const cache::CacheMissSpmResult<T> ms = cache::cache_miss_spm(gamma, m, lam1);
256 missRate = ms.MU;
257 r.pij = cache::cache_prob_spm(gamma, m);
258 r.method = "spm";
259 }
260 return r;
261}
262
263/**
264 * Port of `solver_nc_cache_analyzer.m`.
265 *
266 * @param sn the refreshed struct; must be a Source-Cache-Sink model
267 * @param opt solver controls; `method` selects exact / sampling / spm
268 */
269template <class T>
271 const NcSolverOptions& opt) {
273 if constexpr (!num_traits<T>::has_transcendental) {
274 (void)sn;
275 (void)opt;
276 throw UnsupportedError(ErrorKind{"Arithmetic"},
277 "solver_nc_cache_analyzer: the cache occupancy is a normalizing constant formed in "
278 "logarithms and needs transcendental arithmetic");
279 } else {
280 const T zero = num_traits<T>::from_int(0);
281 const T one = num_traits<T>::from_int(1);
282 const double dnan = std::numeric_limits<double>::quiet_NaN();
283 const std::size_t K = sn.nclasses;
284
285 std::size_t cacheNode = 0, sourceStation = 0;
286 for (std::size_t i = 0; i < sn.nodes.size(); ++i) {
287 if (sn.nodes[i].nodetype == qn::NodeType::Cache) cacheNode = i + 1;
288 if (sn.nodes[i].nodetype == qn::NodeType::Source)
289 sourceStation = sn.nodes[i].station;
290 }
291 if (cacheNode == 0) throw UnsupportedError(ErrorKind{"Topology"}, "solver_nc_cache_analyzer: no Cache node");
292 if (sourceStation == 0) throw UnsupportedError(ErrorKind{"Topology"}, "solver_nc_cache_analyzer: no Source node");
293 const auto itp = sn.nodeparam.find(cacheNode);
294 if (itp == sn.nodeparam.end())
295 throw UnsupportedError(ErrorKind{"Model"}, "solver_nc_cache_analyzer: the Cache node carries no parameters");
296 const qn::CacheParam<T>& ch = itp->second;
297
298 std::vector<T> sourceRate(K, zero);
299 for (std::size_t r = 0; r < K; ++r)
300 if (!sn.disabled[sourceStation - 1][r]) sourceRate[r] = sn.rates(sourceStation - 1, r);
301
302 const std::vector<int>& m = ch.itemcap;
303 const std::size_t n = ch.nitems;
304 // `n < m + 2` in the reference, where `m` is the CAPACITY VECTOR, not
305 // the list count -- and MATLAB's `if` on a vector requires every entry,
306 // so the gate fires only when the item count is short for EVERY list.
307 // Comparing against the number of lists instead lets a cache with more
308 // capacity than items through, where the recursion has no headroom.
309 {
310 bool shortForAll = !m.empty();
311 for (int cap : m)
312 if (static_cast<long>(n) >= static_cast<long>(cap) + 2) shortForAll = false;
313 if (shortForAll)
314 throw UnsupportedError(ErrorKind{"Cache"},
315 "solver_nc_cache_analyzer: NC requires the number of items to exceed the "
316 "cache capacity at least by 2; this cache holds " + std::to_string(n) +
317 " items with capacity " + std::to_string(m[0]));
318 }
319 const std::size_t h = m.size();
320 const std::size_t u = K;
321
322 // lambda[v](k,l): the rate at which class v requests item k while it
323 // sits at node l. The reference fills every list column with the same
324 // rate -- the read rate does not depend on where the item currently is.
325 std::vector<Matrix<T>> lambda(u, Matrix<T>(n, h + 1, zero));
326 for (std::size_t v = 0; v < u; ++v)
327 if (!ch.pread[v].empty())
328 for (std::size_t k = 0; k < n && k < ch.pread[v].size(); ++k)
329 for (std::size_t l = 0; l <= h; ++l)
330 lambda[v](k, l) = T(sourceRate[v] * ch.pread[v][k]);
331
332 // The access-cost matrices. Absent, the reference installs the DEFAULT
333 // LINEAR routing: an item moves from list l to list l+1 on a hit, and
334 // the last list is absorbing.
335 std::vector<std::vector<Matrix<T>>> R = ch.accost;
336 if (R.empty()) {
337 R.assign(u, std::vector<Matrix<T>>(n, Matrix<T>(h + 1, h + 1, zero)));
338 for (std::size_t v = 0; v < u; ++v)
339 for (std::size_t k = 0; k < n; ++k) {
340 Matrix<T> Rm(h + 1, h + 1, zero);
341 for (std::size_t l = 0; l < h; ++l) Rm(l, l + 1) = one;
342 Rm(h, h) = one;
343 R[v][k] = Rm;
344 }
345 }
346
348
349 const NcCacheMiss<T> cm = nc_cache_missrate(gr.gamma, gr.parent, m, n, lambda, ch, opt);
350 const std::vector<int>& sigma = ch.itemsize;
351 const std::vector<int>& costcap = ch.costcap;
352 const std::vector<T>& missRate = cm.missRate;
353 const bool exact = cm.exact;
354 const std::string& method = cm.method;
355 out.pij = cm.pij;
358 if (!cm.warning.empty())
359 out.sol.warning = out.sol.warning.empty() ? cm.warning : out.sol.warning + " " + cm.warning;
360 out.missrate = missRate;
361 // The probabilities the cache table reports, formed where the arrival
362 // rate is still in scope.
363 out.missprob.assign(u, num_traits<T>::from_double(dnan));
364 out.hitprob.assign(u, num_traits<T>::from_double(dnan));
365 for (std::size_t v = 0; v < u; ++v) {
366 if (v >= sourceRate.size()) break;
367 const double lam = num_traits<T>::to_double(sourceRate[v]);
368 if (!(lam > 0.0)) continue;
369 out.missprob[v] = T(missRate[v] / sourceRate[v]);
370 out.hitprob[v] = T(num_traits<T>::from_int(1) - out.missprob[v]);
371 }
372
373 // The metric table. There is no queueing, so only the throughput row of
374 // the Source and the per-class hit/miss split carry anything.
375 const std::size_t M = sn.nstations;
376 out.sol.sol.Q = Matrix<T>(M, K, zero);
377 out.sol.sol.U = Matrix<T>(M, K, zero);
378 out.sol.sol.R = Matrix<T>(M, K, zero);
379 out.sol.sol.Tp = Matrix<T>(M, K, zero);
380 out.sol.sol.C.assign(K, zero);
381 out.sol.sol.X.assign(K, zero);
382 for (std::size_t r = 0; r < K; ++r) out.sol.sol.Tp(sourceStation - 1, r) = sourceRate[r];
383 for (std::size_t r = 0; r < K; ++r) {
384 if (r >= ch.hitclass.size() || r >= ch.missclass.size()) continue;
385 const std::size_t hc = ch.hitclass[r], mc = ch.missclass[r];
386 if (hc == 0 || mc == 0) continue;
387 out.sol.sol.X[mc - 1] = T(out.sol.sol.X[mc - 1] + missRate[r]);
388 out.sol.sol.X[hc - 1] = T(out.sol.sol.X[hc - 1] + (sourceRate[r] - missRate[r]));
389 }
390 out.sol.sol.lG = 0.0;
391 out.sol.sol.iter = 1;
392 out.sol.sol.method = method;
393 out.sol.actualmethod = method;
394
395 // Per-list hit probability, access-weighted. Reported ONLY from the
396 // exact branch, where the per-list columns and the miss column come
397 // from one solution; see the header.
399 if (exact)
400 for (std::size_t v = 0; v < u; ++v) {
401 if (ch.pread[v].empty()) continue;
402 for (std::size_t l = 0; l < h; ++l) {
403 T acc = zero;
404 for (std::size_t k = 0; k < n && k < ch.pread[v].size(); ++k)
405 acc += T(ch.pread[v][k] * out.pij(k, l + 1));
406 out.hitproblist(v, l) = acc;
407 }
408 }
409
410 // Per-item occupancy. Always the EXACT recursion, since the cache is
411 // product-form; skipped above 10 items where it stops being tractable.
412 if (n > 10) {
413 out.itemprob = Matrix<T>(n, h + 1, num_traits<T>::from_double(dnan));
414 } else if (exact) {
415 out.itemprob = out.pij;
416 } else {
417 out.itemprob = cache::cache_prob_erec(gr.gamma, m, sigma, costcap);
418 }
419
420 // Mean storage cost held by each list, K_j = sum_i sigma_i pi_ij. Kept on
421 // the inner NcSolution too, since the runner returns only that and the
422 // cost would otherwise never leave this function.
423 if (!sigma.empty() && out.pij.rows() == n && out.pij.cols() == h + 1) {
424 out.listcost = cache::cache_cost(gr.gamma, m, sigma, costcap, out.pij);
425 out.sol.listcost = out.listcost;
426 }
427 return out;
428 }
429}
430
431/** True when the model is exactly a Source, a Cache and a Sink. */
432template <class T>
434 if (sn.nodes.size() != 3) return false;
435 int src = 0, ca = 0, snk = 0;
436 for (const qn::NodeDef& nd : sn.nodes) {
437 if (nd.nodetype == qn::NodeType::Source) ++src;
438 else if (nd.nodetype == qn::NodeType::Cache) ++ca;
439 else if (nd.nodetype == qn::NodeType::Sink) ++snk;
440 }
441 if (!(src == 1 && ca == 1 && snk == 1)) return false;
442 for (const qn::JobClass& c : sn.classes)
443 if (std::isfinite(c.population) && c.population > 0.0) return false;
444 return true;
445}
446
447} // namespace nc
448} // namespace line
449
450#endif // LINE_SOLVERS_NC_SOLVER_NC_CACHE_H
Mean per-list storage cost of a cache with item sizes, and the screen for promotion paths that storag...
Access factors of a tree-structured multi-list cache.
Cache miss rates from the importance-sampling hit probabilities.
Saddle-point approximation of the cache miss rates.
Exact per-item hit and miss probabilities of a multi-list cache.
Importance-sampling estimate of the cache hit-probability distribution.
Saddle-point approximation of the per-item cache hit probabilities.
Ray (WKB) asymptotic expansion of the cost-capped cache normalizing constant.
InputError(const std::string &what)
Definition error.h:105
UnsupportedError(const std::string &what)
Definition error.h:119
A network plus its refreshed NetworkStruct.
The exception types the port throws.
Dense matrix and non-owning view.
std::vector< CacheBlockedPair > cache_cost_pathcheck(const Matrix< T > &gamma, const std::vector< int > &sigma, const std::vector< int > &k, const std::vector< int > &parent)
Definition cache_cost.h:95
std::vector< T > cache_cost(const Matrix< T > &gamma, const std::vector< int > &m, const std::vector< int > &sigma, const std::vector< int > &k, const Matrix< T > &pij)
Mean per-list storage cost of a cache with item sizes, and the screen for promotion paths that storag...
Definition cache_cost.h:63
CacheGammaResult< T > cache_gamma_lp(const std::vector< Matrix< T > > &lambda, const std::vector< std::vector< Matrix< T > > > &R)
Access factors of a tree-structured multi-list cache.
CacheMissIsResult< T > cache_miss_is(const Matrix< T > &gamma, const std::vector< int > &m, const Matrix< T > &lambda, std::size_t samples, std::uint64_t seed, const std::vector< int > &sigma, const std::vector< int > &cap)
Cache miss rates from the importance-sampling hit probabilities.
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_prob_is(const Matrix< T > &gamma, const std::vector< int > &m, std::size_t samples, std::uint64_t seed, const std::vector< int > &sigma, const std::vector< int > &k)
Importance-sampling estimate of the cache hit-probability distribution.
CacheSpmSizeResult< T > cache_spm_size(const Matrix< T > &gamma, const std::vector< int > &m, const std::vector< int > &sigma, const std::vector< int > &k, CacheCostMode mode=CacheCostMode::AtMost)
Ray (WKB) asymptotic expansion of the cost-capped cache normalizing constant.
CacheMissSpmResult< T > cache_miss_spm(const Matrix< T > &gamma, const std::vector< int > &m, const Matrix< T > &lambda)
Saddle-point approximation of the cache miss rates.
Matrix< T > cache_prob_spm(const Matrix< T > &gamma, const std::vector< int > &m)
Saddle-point approximation of the per-item cache hit probabilities.
@ FIFO
first in, first out
Definition lang_types.h:415
NcCacheMiss< T > nc_cache_missrate(const Matrix< T > &gamma, const std::vector< int > &parent, const std::vector< int > &m, std::size_t n, const std::vector< Matrix< T > > &lambda, const qn::CacheParam< T > &ch, const NcSolverOptions &opt)
Miss rates of an isolated cache under opt.method, honouring the per-item storage costs and per-list c...
NcCacheSolution< T > solver_nc_cache_analyzer(const qn::NetworkStruct< T > &sn, const NcSolverOptions &opt)
Port of solver_nc_cache_analyzer.m.
bool nc_is_noreentrant_cache(const qn::NetworkStruct< T > &sn)
True when the model is exactly a Source, a Cache and a Sink.
Conservation laws of a layered queueing network, enumerated from its structure.
Definition aoi_dist2ph.h:52
Controls and result shape shared by the normalizing-constant analyzers.
A queueing network and its refreshed NetworkStruct.
Port of solver_nc.m: the load-INDEPENDENT normalizing-constant analyzer.
The <kind> part of a LINE:<category>:<kind> identifier (see _kb/17-error-vocabulary....
Definition error.h:37
Return value of cache_gamma_lp, mirroring [gamma,u,n,h].
std::vector< int > parent
Parent list of each list, 0-based, -1 for lists rooted in the miss list.
Matrix< T > gamma
(n x h) access factors
std::vector< T > MU
(u) per-user miss rate; empty when no lambda given
Return value of cache_miss_spm, mirroring [M,MU,MI,pi0,lE].
std::vector< T > MU
(u) per-user miss rate
Outcome of the expansion.
Matrix< T > pij
Occupancy pi, n x (h+1), column 0 the miss probability.
Miss rates of one isolated cache and what produced them; see nc_cache_missrate.
std::vector< cache::CacheBlockedPair > costcap_blocked
std::vector< T > missRate
(u) miss rate of each user class
bool exact
pij came from the exact recursion
Matrix< T > pij
(n x h+1) item occupancy of the chosen method, column 0 the miss one
What the cache analyzer returns beyond the usual metric table.
Matrix< T > hitproblist
(u x h) access-weighted per-list hit probability, NaN if not exact
Matrix< T > pij
(n x h+1) per-item occupancy, column 0 = miss
std::vector< T > missrate
(u) per-class miss rate
std::vector< cache::CacheBlockedPair > costcap_blocked
Storage cost caps that block a promotion path, so that the exact recursion normalizes over MORE state...
std::vector< T > missprob
(u) per-class miss and hit PROBABILITIES, missrate divided by the read class's arrival rate and its c...
Matrix< T > itemprob
(n x h+1) the same from the EXACT recursion, NaN above 10 items
bool costcap_method_switched
True when the requested method had no cost-capped counterpart and was switched.
std::vector< T > listcost
(h) mean storage cost held by each list, EMPTY without item sizes
The [Q,U,R,T,C,X,lG] of the reference, plus the algorithm that ran.
Definition nc_types.h:134
Controls, defaulting to SolverOptions('NC') in the reference.
Definition nc_types.h:35
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
lang::ReplacementStrategy replacestrat
One job class of the network.
double population
infinite for an open class
A node of the network.