LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
cache_miss_spm.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_SPM_H
6#define LINE_API_CACHE_MISS_SPM_H
7
8/**
9 * @file
10 * @ingroup api_cache
11 * Saddle-point approximation of the cache miss rates.
12 *
13 * Templated port of matlab/src/api/cache/cache_miss_spm.m, cross-checked
14 * against jar/src/main/java/jline/api/cache/Cache_miss_rayint.java.
15 *
16 * Identical structure to cache_miss, with every exact constant replaced by the
17 * cache_spm approximation of its logarithm:
18 *
19 * M = exp(lE(gamma, m + e_1) - lE(gamma, m)),
20 * pi0(k) = exp(lE(gamma without item k, m) - lE(gamma, m)),
21 * MU(v) = sum_k lambda(v,k) pi0(k), MI(k) = (sum_v lambda(v,k)) pi0(k).
22 *
23 * Items with an all-zero access-factor row are never cached and are skipped,
24 * contributing pi0 = 0 and MI = 0 exactly as in the reference.
25 *
26 * ARITHMETIC: transcendental, inherited from cache_spm.
27 *
28 * REFERENCE DEFECT (MATLAB): the "recompute xi" fallback taken when a pi0(k)
29 * falls outside [0,1] re-invokes cache_spm without the warm start, but the
30 * warm start never had any effect in the first place -- cache_spm forwards it
31 * to cache_xi_iter's third argument, which that function declares as `tmax`
32 * and never reads. The two branches are therefore the same computation, so
33 * this port evaluates lE1(k) once. This changes no value; it only removes a
34 * duplicated call.
35 */
36
37#include <cmath>
38#include <cstddef>
39#include <vector>
40
44#include "line/num/number.h"
45#include "line/util/error.h"
46#include "line/util/matrix.h"
47
48namespace line {
49namespace cache {
50
51/** Return value of cache_miss_spm, mirroring [M,MU,MI,pi0,lE]. */
52template <class T>
54 T M; ///< global miss rate
55 std::vector<T> MU; ///< (u) per-user miss rate
56 std::vector<T> MI; ///< (n) per-item miss rate
57 std::vector<T> pi0; ///< (n) per-item miss probability
58 T lE; ///< log normalizing constant at capacity m
59};
60
61/**
62 * @brief Saddle-point approximation of the cache miss rates.
63 *
64 * @param gamma (n x h) access factors
65 * @param m (h) list capacities
66 * @param lambda (u x n) per-user per-item request rates
67 */
68template <class T>
69CacheMissSpmResult<T> cache_miss_spm(const Matrix<T>& gamma, const std::vector<int>& m,
70 const Matrix<T>& lambda) {
72 "cache_miss_spm requires transcendental arithmetic");
73 using std::exp;
74 if (m.empty()) throw InputError("cache_miss_spm: empty capacity vector");
75 const std::size_t n = gamma.rows();
76 const std::size_t h = gamma.cols();
77 if (h != m.size()) throw InputError("cache_miss_spm: gamma and m disagree on the list count");
78
79 std::vector<int> ma = m;
80 ma[0] += 1;
81
82 const T zero = num_traits<T>::from_int(0);
84 r.lE = cache_spm(gamma, m).lZ;
85 const T lEa = cache_spm(gamma, ma).lZ;
86 r.M = exp(T(lEa - r.lE));
87
88 if (lambda.empty()) return r;
89 if (lambda.cols() != n)
90 throw InputError("cache_miss_spm: lambda and gamma disagree on the number of items");
91 const std::size_t u = lambda.rows();
92
93 r.pi0.assign(n, zero);
94 r.MI.assign(n, zero);
95 r.MU.assign(u, zero);
96
97 for (std::size_t k = 0; k < n; ++k) {
98 T rowsum = zero;
99 for (std::size_t l = 0; l < h; ++l) rowsum += gamma(k, l);
100 if (!(rowsum > zero)) continue; // never cached: pi0 = 0, MI = 0
101
102 const T lE1 = cache_spm(detail::gamma_without_row(gamma, k), m).lZ;
103 r.pi0[k] = exp(T(lE1 - r.lE));
104 T lam = zero;
105 for (std::size_t v = 0; v < u; ++v) {
106 r.MU[v] += lambda(v, k) * r.pi0[k];
107 lam += lambda(v, k);
108 }
109 r.MI[k] = lam * r.pi0[k];
110 }
111 return r;
112}
113
114} // namespace cache
115} // namespace line
116
117#endif // LINE_API_CACHE_MISS_SPM_H
Exact recursive normalizing constant of a multi-list cache model.
Exact cache miss rates from the recursive normalizing constant.
Saddle-point approximation of the cache normalizing constant.
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
bool empty() const
Definition matrix.h:92
The exception types the port throws.
Dense matrix and non-owning view.
CacheSpmResult< T > cache_spm(const Matrix< T > &gamma_in, const std::vector< int > &m)
Saddle-point approximation of the cache normalizing constant.
Definition cache_spm.h:152
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.
Number-type abstraction for the templated API port.
Return value of cache_miss_spm, mirroring [M,MU,MI,pi0,lE].
T lE
log normalizing constant at capacity m
std::vector< T > pi0
(n) per-item miss probability
std::vector< T > MI
(n) per-item miss rate
std::vector< T > MU
(u) per-user miss rate