122 const std::vector<T>& lambda,
128 "retrieval_fpi_latency requires transcendental arithmetic: it is driven by "
129 "retrieval_fpi, a successive substitution stopped on a relative tolerance");
130 const std::size_t n = lambda.size();
131 const std::size_t S = station.size();
132 if (S == 0)
throw InputError(
"retrieval_fpi_latency: no retrieval station");
133 if (gamma.
rows() != n)
134 throw InputError(
"retrieval_fpi_latency: gamma and lambda disagree on the item count");
136 throw InputError(
"retrieval_fpi_latency: one routing matrix per item is required");
137 for (std::size_t i = 0; i < n; ++i)
138 if (R[i].rows() != S + 1 || R[i].cols() != S + 1)
139 throw InputError(
"retrieval_fpi_latency: routing matrices must be (S+1) x (S+1)");
141 std::vector<std::size_t> fsz(S);
142 for (std::size_t s = 0; s < S; ++s) {
143 fsz[s] = station[s].phases();
144 if (station[s].sub.
size() != n)
145 throw InputError(
"retrieval_fpi_latency: one subgenerator per item is required");
146 if (station[s].alpha.rows() != n)
147 throw InputError(
"retrieval_fpi_latency: alpha must have one row per item");
148 for (std::size_t i = 0; i < n; ++i)
149 if (station[s].sub[i].rows() != fsz[s] || station[s].sub[i].cols() != fsz[s])
150 throw InputError(
"retrieval_fpi_latency: subgenerator size disagrees with alpha");
156 "retrieval_fpi_latency: SIRO/FCFS retrieval stations require exponential "
157 "(single-phase) service");
162 for (std::size_t s = 0; s < S; ++s)
163 for (std::size_t i = 0; i < n; ++i) {
165 for (std::size_t k = 0; k < fsz[s]; ++k) arow(0, k) = station[s].alpha(i, k);
166 tau(i, s) = detail::ph_mean(arow, station[s].sub[i]);
170 for (std::size_t s = 0; s < S; ++s) {
174 double lo = 0.0, hi = 0.0;
175 for (std::size_t i = 0; i < n; ++i) {
177 if (i == 0 || x < lo) lo = x;
178 if (i == 0 || x > hi) hi = x;
180 if (hi - lo > 1e-9 * hi)
182 "retrieval_fpi_latency: SIRO/FCFS retrieval stations require class-independent "
183 "mean service rates");
187 std::vector<std::size_t> is_idx, ps_idx;
188 for (std::size_t s = 0; s < S; ++s) {
194 const std::size_t r = ps_idx.size();
198 for (std::size_t i = 0; i < n; ++i) {
200 for (std::size_t a = 0; a < S; ++a)
201 for (std::size_t b = 0; b < S; ++b)
206 for (std::size_t b = 0; b < S; ++b)
207 for (std::size_t a = 0; a < S; ++a) visits[b] += R[i](0, a + 1) * Vinv(a, b);
210 for (std::size_t s : is_idx) is_sum += visits[s] * tau(i, s);
212 for (std::size_t p = 0; p < r; ++p) eta(i, 1 + p) = visits[ps_idx[p]] * tau(i, ps_idx[p]);
220 for (std::size_t i = 0; i < n; ++i)
221 for (std::size_t s = 0; s <= r; ++s) out.
phi[i] += full.
pdh(s, i);
224 const std::size_t Phi = [&]() {
226 for (std::size_t s = 0; s < S; ++s) t += fsz[s];
229 std::vector<std::size_t> off(S, 0);
230 for (std::size_t s = 1; s < S; ++s) off[s] = off[s - 1] + fsz[s - 1];
232 for (std::size_t i = 0; i < n; ++i) {
243 for (std::size_t p = 0; p < r; ++p) {
245 for (std::size_t k = 0; k < n; ++k)
246 if (k != i) acc += full.
pdh(1 + p, k);
247 phitilde[ps_idx[p]] = acc;
253 for (std::size_t s = 0; s < S; ++s) {
259 for (std::size_t a = 0; a < fsz[s]; ++a)
260 for (std::size_t b = 0; b < fsz[s]; ++b) blk(a, b) = scale * station[s].sub[i](a, b);
261 for (std::size_t a = 0; a < fsz[s]; ++a)
262 for (std::size_t b = 0; b < fsz[s]; ++b) D0(off[s] + a, off[s] + b) += blk(a, b);
265 for (std::size_t a = 0; a < fsz[s]; ++a) {
267 for (std::size_t b = 0; b < fsz[s]; ++b) acc += blk(a, b);
270 for (std::size_t sp = 0; sp < S; ++sp)
271 for (std::size_t a = 0; a < fsz[s]; ++a)
272 for (std::size_t b = 0; b < fsz[sp]; ++b)
273 D0(off[s] + a, off[sp] + b) +=
274 compl_[a] * R[i](s + 1, sp + 1) * station[sp].alpha(i, b);
275 for (std::size_t a = 0; a < fsz[s]; ++a)
276 pe[off[s] + a] = R[i](0, s + 1) * station[s].alpha(i, a);
281 for (std::size_t a = 0; a < Phi; ++a)
282 for (std::size_t b = 0; b < Phi; ++b) A(a, b) = -D0(a, b);
284 const std::vector<std::size_t> piv =
lu_factor(LU);
287 std::vector<T> y2 = y;
290 for (std::size_t a = 0; a < Phi; ++a) {
296 throw NumericError(
"retrieval_fpi_latency: zero mean fetch period");
302 for (std::size_t i = 0; i < n; ++i) {
303 num += out.
phi[i] + out.
d[i];
304 den += lambda[i] * (out.
phi[i] + out.
pi0[i]);
307 throw NumericError(
"retrieval_fpi_latency: no fetching traffic, the latency is undefined");
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 ...