LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
solver_mva_retrieval.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_MVA_SOLVER_MVA_RETRIEVAL_H
6#define LINE_SOLVERS_MVA_SOLVER_MVA_RETRIEVAL_H
7
8/**
9 * @file
10 * @ingroup line_solvers
11 * Delayed-hit (retrieval-system) cache analyzer, a port of
12 * matlab/src/solvers/MVA/solver_mva_retrieval_analyzer.m.
13 *
14 * A miss triggers a per-item retrieval class that fetches the item through the
15 * retrieval queues and returns to the cache; a read arriving while a fetch is in
16 * flight is a DELAYED hit. The fixed-point algorithms decide the hit / miss /
17 * delayed-hit ratios (`retrieval_fpi`) and the expected latency and per-item
18 * queueing (`retrieval_fpi_latency`); this glue reads the inputs
19 * (`cache_retrieval_inputs`) and assembles the per-station mean queue length,
20 * utilization, response time and throughput of the retrieval sub-network.
21 *
22 * ARITHMETIC: transcendental (the FPIs iterate to a tolerance and fit
23 * distributions), so it refuses under Rational by name.
24 */
25
26#include <limits>
27#include <vector>
28
33#include "line/util/linalg.h"
34
35namespace line {
36namespace mva {
37
38/**
39 * The cache half of the reference's return list: `hitprob`, `missprob`,
40 * `delayedprob`, `latency`, `hitproblist` and `itemprob` of
41 * `solver_mva_retrieval_analyzer.m`. Optional, because the analyzer is also
42 * called for the station tables alone (cpp/examples/basic/cacheModel.cpp).
43 */
44template <class T>
47 Matrix<T> hitproblist; ///< (K x h)
48 Matrix<T> itemprob; ///< (n x h+1), column 0 = miss
49};
50
51template <class T>
53 MvaRetrievalCacheOutputs<T>* cache_out = nullptr) {
54 if constexpr (!num_traits<T>::has_transcendental) {
55 throw UnsupportedError(
56 "solver_mva_retrieval_analyzer: the delayed-hit retrieval fixed point needs "
57 "transcendental arithmetic; rerun with --arith double or --arith real");
58 } else {
59 const T zero = num_traits<T>::from_int(0);
60 const std::size_t M = L.nstations, K = L.nclasses;
62 const std::size_t n = in.lambda.size(), S = in.queue_nodes.size();
63 const std::size_t jobin = in.read_class;
64
69
71 s.Q = Matrix<T>(M, K, zero);
72 s.U = Matrix<T>(M, K, zero);
73 s.R = Matrix<T>(M, K, zero);
74 s.Tp = Matrix<T>(M, K, zero);
75 s.X.assign(K, zero);
76 s.method = "fpi";
77 s.iter = 1;
78
79 // per-item weights and class aggregates (single read class, IRM)
80 T lamsum = zero;
81 for (std::size_t i = 0; i < n; ++i) lamsum = T(lamsum + in.lambda[i]);
82 std::vector<T> w(n, zero);
83 for (std::size_t i = 0; i < n; ++i) w[i] = lamsum > zero ? T(in.lambda[i] / lamsum) : zero;
84 T hitAgg = zero, missAgg = zero, delayedAgg = zero;
85 for (std::size_t i = 0; i < n; ++i) {
86 T pih = zero; // sum over lists of the hit ratio
87 for (std::size_t l = 0; l < fp.phit.rows(); ++l) pih = T(pih + fp.phit(l, i));
88 missAgg = T(missAgg + w[i] * fp.pmiss[i]);
89 hitAgg = T(hitAgg + w[i] * pih);
90 delayedAgg = T(delayedAgg + w[i] * lat.phi[i]);
91 }
92
93 // The cache answer, in the reference's per-class layout: NaN marks a
94 // class that does not read this cache, which is what getAvgCacheTable
95 // tests to decide the class has no row at all.
96 if (cache_out) {
97 const T nan = num_traits<T>::from_double(std::numeric_limits<double>::quiet_NaN());
98 cache_out->hitprob.assign(K, nan);
99 cache_out->missprob.assign(K, nan);
100 cache_out->delayedprob.assign(K, nan);
101 cache_out->latency.assign(K, nan);
102 if (jobin >= 1 && jobin <= K) {
103 cache_out->hitprob[jobin - 1] = hitAgg;
104 cache_out->missprob[jobin - 1] = missAgg;
105 cache_out->delayedprob[jobin - 1] = delayedAgg;
106 cache_out->latency[jobin - 1] = lat.Z;
107 }
108 // per-list hit fractions for the read class, access-weighted over
109 // items: `(phit * w).'` of the reference. Rows sum to hitAgg.
110 const std::size_t h = fp.phit.rows();
111 cache_out->hitproblist = Matrix<T>(K, h, nan);
112 if (jobin >= 1 && jobin <= K)
113 for (std::size_t l = 0; l < h; ++l) {
114 T acc = zero;
115 for (std::size_t i = 0; i < n; ++i) acc = T(acc + fp.phit(l, i) * w[i]);
116 cache_out->hitproblist(jobin - 1, l) = acc;
117 }
118 // per-item occupancy `[pi0(:), phit.']`: column 0 is the miss.
119 cache_out->itemprob = Matrix<T>(n, h + 1, zero);
120 for (std::size_t i = 0; i < n; ++i) {
121 cache_out->itemprob(i, 0) = fp.pmiss[i];
122 for (std::size_t l = 0; l < h; ++l) cache_out->itemprob(i, l + 1) = fp.phit(l, i);
123 }
124 }
125
126 // source throughput and the hit/miss class throughputs
127 const std::size_t src_st = L.sourceIdx;
128 const T sourceRate =
129 L.disabled[src_st - 1][jobin - 1] ? zero : L.rates(src_st - 1, jobin - 1);
130 s.Tp(src_st - 1, jobin - 1) = sourceRate;
131 const qn::CacheParam<T>& ch = [&]() -> const qn::CacheParam<T>& {
132 for (const auto& kv : L.nodeparam)
133 if (L.nodes[kv.first - 1].nodetype == qn::NodeType::Cache) return kv.second;
134 throw InputError("solver_mva_retrieval_analyzer: no cache");
135 }();
136 const std::size_t hc = (jobin - 1) < ch.hitclass.size() ? ch.hitclass[jobin - 1] : 0;
137 const std::size_t mc = (jobin - 1) < ch.missclass.size() ? ch.missclass[jobin - 1] : 0;
138 if (hc > 0) s.X[hc - 1] = T(sourceRate * (hitAgg + delayedAgg));
139 if (mc > 0) s.X[mc - 1] = T(sourceRate * missAgg);
140
141 // per-retrieval-station occupancy (delayed hits), throughput, response
142 std::vector<std::size_t> psIdx;
143 for (std::size_t si = 0; si < S; ++si)
144 if (in.station[si].type != retrieval::RetrievalStationType::IS) psIdx.push_back(si);
145 for (std::size_t si = 0; si < S; ++si) {
146 const std::size_t st = L.nodes[in.queue_nodes[si] - 1].station;
147 std::size_t prow = 0; // IS aggregate row
148 if (in.station[si].type != retrieval::RetrievalStationType::IS) {
149 for (std::size_t p = 0; p < psIdx.size(); ++p)
150 if (psIdx[p] == si) prow = 1 + p;
151 }
152 T phi_s = zero;
153 if (prow < fp.pdh.rows())
154 for (std::size_t i = 0; i < n; ++i) phi_s = T(phi_s + fp.pdh(prow, i));
155 // throughput: miss traffic times the per-item station visits
156 T tput_s = zero;
157 for (std::size_t i = 0; i < n; ++i) {
158 Matrix<T> ImP(S, S, zero);
159 std::vector<T> a(S, zero);
160 for (std::size_t x = 0; x < S; ++x) {
161 a[x] = in.R[i](0, x + 1);
162 for (std::size_t y = 0; y < S; ++y)
163 ImP(x, y) = T((x == y ? num_traits<T>::from_int(1) : zero) -
164 in.R[i](x + 1, y + 1));
165 }
166 const Matrix<T> F = inverse(ImP);
167 T vis = zero;
168 for (std::size_t y = 0; y < S; ++y) vis = T(vis + a[y] * F(y, si));
169 tput_s = T(tput_s + sourceRate * w[i] * fp.pmiss[i] * vis);
170 }
171 s.Q(st - 1, jobin - 1) = phi_s;
172 s.U(st - 1, jobin - 1) = phi_s;
173 s.Tp(st - 1, jobin - 1) = tput_s;
174 if (tput_s > zero) s.R(st - 1, jobin - 1) = T(phi_s / tput_s);
175 }
176 (void)opt;
177 return s;
178 }
179}
180
181} // namespace mva
182} // namespace line
183
184#endif // LINE_SOLVERS_MVA_SOLVER_MVA_RETRIEVAL_H
Extract the delayed-hit retrieval-algorithm inputs from a NetworkStruct, a port of matlab/src/api/ret...
InputError(const std::string &what)
Definition error.h:39
UnsupportedError(const std::string &what)
Definition error.h:51
A network plus its refreshed NetworkStruct.
std::size_t sourceIdx
1-based station index of the Source, 0 = none
std::vector< std::vector< bool > > disabled
std::map< std::size_t, CacheParam< T > > nodeparam
Cache parameters by 1-based NODE index; only Cache nodes have an entry.
Matrix< T > rates
(nstations x nclasses) service rates and SCVs, with a PARALLEL disabled flag instead of MATLAB's NaN ...
std::vector< NodeDef > nodes
every node, in creation order
Dense linear algebra over the templated number type: products, identity, inverse, and powers.
The option and result types every MVA analyzer shares.
MvaSolution< T > solver_mva_retrieval_analyzer(const qn::NetworkStruct< T > &L, const MvaOptions &opt, MvaRetrievalCacheOutputs< T > *cache_out=nullptr)
RetrievalInputs< T > cache_retrieval_inputs(const qn::NetworkStruct< T > &sn, double lambda_override=-1.0)
Extract the delayed-hit retrieval-algorithm inputs from a NetworkStruct, a port of matlab/src/api/ret...
RetrievalFpiLatencyResult< T > retrieval_fpi_latency(const std::vector< int > &m, const std::vector< T > &lambda, const Matrix< T > &gamma, const std::vector< RetrievalStationPH< T > > &station, const std::vector< Matrix< T > > &R, const FpiOptions &options=FpiOptions())
FPI-based approximation of the delayed-hit count and the expected latency of a list-based cache with ...
RetrievalFpiResult< T > retrieval_fpi(const std::vector< int > &m, const std::vector< T > &lambda, const Matrix< T > &eta, const Matrix< T > &gamma, const FpiOptions &options=FpiOptions())
Fixed-point heuristic for a delayed-hit (list-based) cache.
Matrix< T > inverse(const Matrix< T > &A)
Inverse by LU with one factorization and n back substitutions.
Definition linalg.h:72
Fixed-point heuristic for a delayed-hit (list-based) cache.
FPI-based approximation of the delayed-hit count and the expected latency of a list-based cache with ...
The options SolverMVA reads.
Definition mva_types.h:31
The cache half of the reference's return list: hitprob, missprob, delayedprob, latency,...
Matrix< T > itemprob
(n x h+1), column 0 = miss
Class-level results, the [Q,U,R,T,C,X] of the MATLAB analyzers.
Definition mva_types.h:96
std::vector< T > X
Definition mva_types.h:98
std::vector< std::size_t > missclass
std::vector< std::size_t > hitclass
Mirrors the [Z, d, phi, pi0] return list of the MATLAB function.
T Z
expected latency of the delayed-hit system
std::vector< T > phi
(n) delayed-hit ratio phi_i
Mirrors the [pmiss, phit, pdh] return list, plus the iteration diagnostics.
Matrix< T > phit
(h x n) hit ratios pi_{i,j}
Matrix< T > pdh
((r+1) x n) delayed-hit probabilities phi_{s,i}, s = 0..r
std::vector< T > pmiss
(n) miss ratios pi_{i,0}
The [m, lambda, gamma, eta, alpha/T (station), R] the retrieval algorithms read.
std::vector< int > m
(h) list capacities
std::vector< Matrix< T > > R
(n) routing over cache+stations, (S+1)x(S+1)
std::size_t read_class
1-based read (job-in) class
Matrix< T > gamma
(n x h) access factors
std::vector< std::size_t > queue_nodes
1-based retrieval station nodes
std::vector< T > lambda
(n) per-item arrival rates
std::vector< RetrievalStationPH< T > > station
(S) per-station PH service + type
Matrix< T > eta
(n x (r+1)) fetching demands