LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
cache_miss_asy.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_CACHE_MISS_ASY_H
6#define LINE_API_CACHE_MISS_ASY_H
7
8/**
9 * @file
10 * @ingroup api_cache
11 * Asymptotic (large-cache) miss ratio by a rank-threshold fixed point.
12 *
13 * Templated port of jar/src/main/java/jline/api/cache/Cache_miss_asy.java.
14 * MATLAB has no counterpart, so the JAR is the reference.
15 *
16 * The deterministic limit of a multi-list cache: as the item count grows, list
17 * l holds exactly the m(l) items of largest effective popularity, so an item's
18 * membership becomes a THRESHOLD test rather than a probability. Writing
19 * pi(k) for the miss probability of item k, the effective popularity of item j
20 * in list l is gamma(l,j) (1 - pi(j)) and the fixed point is
21 *
22 * pi(k) = sum_l gamma(l,k) 1{item k is outside the top m(l)} / sum_l gamma(l,k),
23 *
24 * iterated to a sup-norm tolerance from the uniform start pi = 1/n. The
25 * returned scalar is the request-weighted miss ratio
26 * sum_{l,k} gamma(l,k) pi(k) / sum_{l,k} gamma(l,k).
27 *
28 * INDEX CONVENTION, AND IT IS THE REVERSE OF EVERY OTHER CACHE FUNCTION HERE.
29 * The reference reads n = gamma.getNumCols() and h = gamma.getNumRows(), so
30 * its gamma is (h x n), LIST-major, whereas cache_spm, cache_erec, cache_miss
31 * and the rest all take gamma as (n x h), ITEM-major. That is reproduced,
32 * because silently transposing would make the two conventions disagree about
33 * which of a non-square gamma's dimensions is the item count and return a
34 * plausible wrong ratio rather than an error. Callers holding an item-major
35 * gamma must transpose before calling.
36 *
37 * The threshold is strict (`>`), so ties at the cutoff resolve as "in cache".
38 * With the ranking taken over the OTHER n-1 items and then compared against
39 * item k, an item exactly at the boundary is admitted; this reproduces the
40 * reference and matters only on gamma matrices with repeated entries.
41 *
42 * A degenerate capacity (zero total, or any negative entry) returns 1, i.e.
43 * every request misses, which is the reference's early exit.
44 *
45 * Arithmetic: EXACT-CAPABLE in its operations, but the answer is defined by a
46 * sup-norm tolerance and an iteration cap, so it is inexact by construction
47 * and gated on transcendental arithmetic like the other fixed-point cache
48 * routines (cache_xi_iter, cache_miss_fpi).
49 */
50
51#include <algorithm>
52#include <cstddef>
53#include <vector>
54
55#include "line/num/number.h"
56#include "line/util/error.h"
57#include "line/util/matrix.h"
58
59namespace line {
60namespace cache {
61
62/**
63 * @brief Asymptotic (large-cache) miss ratio by a rank-threshold fixed point.
64 *
65 * @param gamma (h x n) LIST-major access factors; see the note above
66 * @param m (h) list capacities
67 * @param maxIter cap on fixed-point sweeps
68 * @param tolerance sup-norm stopping tolerance on pi
69 * @return the request-weighted asymptotic miss ratio
70 */
71template <class T>
72T cache_miss_asy(const Matrix<T>& gamma, const std::vector<int>& m, int maxIter,
73 const T& tolerance) {
75 "cache_miss_asy is a tolerance-stopped fixed point and needs transcendental "
76 "arithmetic");
77 const std::size_t h = gamma.rows();
78 const std::size_t n = gamma.cols();
79 if (m.size() != h)
80 throw InputError("cache_miss_asy: gamma is list-major and disagrees with m on the list "
81 "count");
82 if (n == 0) throw InputError("cache_miss_asy: no items");
83
84 const T zero = num_traits<T>::from_int(0);
85 const T one = num_traits<T>::from_int(1);
86
87 long mtot = 0;
88 for (std::size_t l = 0; l < h; ++l) {
89 if (m[l] < 0) return one;
90 mtot += m[l];
91 }
92 if (mtot == 0) return one;
93
94 // GlobalConstants.Zero, the reference's test for a vanishing rate sum
95 const T tiny = num_traits<T>::from_double(1e-14);
96
97 std::vector<T> pi(n, T(one / num_traits<T>::from_int(static_cast<long>(n))));
98 std::vector<T> prev(n, zero);
99 std::vector<T> next(n, zero);
100 std::vector<T> pop; // effective popularities of the other items, reused
101 pop.reserve(n);
102
103 for (int iter = 0; iter < maxIter; ++iter) {
104 prev = pi;
105 for (std::size_t k = 0; k < n; ++k) {
106 T numer = zero, denom = zero;
107 for (std::size_t l = 0; l < h; ++l) {
108 const int cap = m[l];
109 if (cap <= 0) continue;
110 pop.clear();
111 for (std::size_t j = 0; j < n; ++j)
112 if (j != k) pop.push_back(T(gamma(l, j) * T(one - prev[j])));
113 // descending, so the take-th entry is the weakest still cached
114 std::sort(pop.begin(), pop.end(), [](const T& a, const T& b) { return b < a; });
115 const std::size_t take =
116 std::min(static_cast<std::size_t>(cap), pop.size());
117
118 T notInCache = one;
119 if (take < static_cast<std::size_t>(cap)) {
120 // fewer competitors than slots: item k is always cached
121 notInCache = zero;
122 } else if (take > 0) {
123 const T weakest = pop[take - 1];
124 if (T(gamma(l, k) * T(one - prev[k])) > weakest) notInCache = zero;
125 }
126 numer += gamma(l, k) * notInCache;
127 denom += gamma(l, k);
128 }
129 next[k] = denom > tiny ? T(numer / denom) : one;
130 }
131 pi = next;
132
133 T diff = zero;
134 for (std::size_t k = 0; k < n; ++k) {
135 const T d = num_abs(T(pi[k] - prev[k]));
136 if (d > diff) diff = d;
137 }
138 if (diff < tolerance) break;
139 }
140
141 T missRate = zero, totalRate = zero;
142 for (std::size_t l = 0; l < h; ++l) {
143 for (std::size_t k = 0; k < n; ++k) {
144 missRate += gamma(l, k) * pi[k];
145 totalRate += gamma(l, k);
146 }
147 }
148 return totalRate > tiny ? T(missRate / totalRate) : one;
149}
150
151/** Reference defaults: 1000 sweeps at a 1e-8 sup-norm tolerance. */
152template <class T>
153T cache_miss_asy(const Matrix<T>& gamma, const std::vector<int>& m) {
154 return cache_miss_asy(gamma, m, 1000, num_traits<T>::from_double(1e-8));
155}
156
157} // namespace cache
158} // namespace line
159
160#endif // LINE_API_CACHE_MISS_ASY_H
InputError(const std::string &what)
Definition error.h:39
std::size_t cols() const
Definition matrix.h:90
std::size_t rows() const
Definition matrix.h:89
The exception types the port throws.
Dense matrix and non-owning view.
T cache_miss_asy(const Matrix< T > &gamma, const std::vector< int > &m, int maxIter, const T &tolerance)
Asymptotic (large-cache) miss ratio by a rank-threshold fixed point.
T num_abs(const T &v)
Definition number.h:172
Number-type abstraction for the templated API port.