LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
cache_mmap_rr_env.m
1% MMAP-fed small RR cache with two correlated classes.
2%
3% A marked MMPP2 arrival stream feeds a small Round-Robin (RR) cache. Its two
4% marks are bound to two open read classes that share the modulating chain, so
5% the classes are cross-correlated and autocorrelated in time. Each class reads
6% the cache with a DIFFERENT item-popularity distribution.
7%
8% Phase 1 (bursty) emits mostly class-1 references at a high rate; phase 2
9% (calm) emits mostly class-2 references at a low rate. The shared modulating
10% chain therefore couples "which class arrives" with "how fast requests arrive".
11%
12% We solve the same system three ways:
13% (1) LDES - discrete-event simulation of the true MMAP-fed cache;
14% (2) CTMC - exact continuous-time Markov chain of the true system;
15% (3) ENV - three random-environment methods that view the MMPP2 phase as
16% an environment modulating phase-conditional Poisson arrivals
17% (D1 diagonal):
18% 'avg' - fast-environment limit: replace the modulation by its
19% time-average per-class Poisson rates and solve ONE
20% rate-averaged cache;
21% 'dec' - slow-environment limit: quasi-stationary
22% decomposition, solve each phase independently and
23% average per-phase hit ratios weighted by phase prob;
24% 'blend' - state-vector coupling: carry the cache-state
25% distribution across phase switches and average each
26% phase's sojourn-weighted distribution. For a
27% Markovian environment this recovers the exact joint
28% (cache x phase) solution, i.e. it matches CTMC.
29% The 'avg' and 'dec' limits discard the within-phase temporal correlation of
30% references, so neither is guaranteed to bracket the exact value.
31
32clear solver AvgTable;
33
34n = 4; % number of items
35m = 2; % cache capacity
36
37% Per-class item-popularity distributions (deliberately different)
38pAccess1 = DiscreteSampler([8 4 2 1]/15); % class 1 favors low-index items
39pAccess2 = DiscreteSampler([1 2 4 8]/15); % class 2 favors high-index items
40
41% Marked MMPP2 (M3A layout D = {D0, D11, D12}); D1 = D11 + D12 diagonal.
42% Phase 1 bursty (rate 4, 90% class1); phase 2 calm (rate 1, 80% class2).
43% Off-diagonal of D0 are the phase-switch rates (both 0.5).
44D0 = [-4.5, 0.5; 0.5, -1.5];
45D11 = [3.6, 0; 0, 0.2]; % class-1 arrivals per phase
46D12 = [0.4, 0; 0, 0.8]; % class-2 arrivals per phase
47mmap = MarkedMAP({D0, D11, D12}, 2);
48
49%% (1) LDES - simulation of the true MMAP-fed cache
50trueModel = buildCacheModel(n, m, pAccess1, pAccess2);
51src = trueModel.getNodeByName('Source');
52src.setMarkedArrival(mmap, {trueModel.classes{1}, trueModel.classes{2}});
53cacheTrue = trueModel.getNodeByName('Cache');
54
55solver{1} = LDES(trueModel, 'samples', 2e5, 'seed', 23000, 'verbose', true);
56AvgTable{1} = solver{1}.getAvgNodeTable; AvgTable{1}
57hitLDES = cacheTrue.getHitRatio;
58
59%% (2) CTMC - exact solution of the true system
60trueModel.reset;
61solver{2} = CTMC(trueModel, 'keep', false, 'cutoff', 1);
62AvgTable{2} = solver{2}.getAvgNodeTable; AvgTable{2}
63hitCTMC = cacheTrue.getHitRatio;
64
65%% Random environment: the MMPP2 phase modulates phase-conditional Poisson
66% arrivals (D1 diagonal); the environment switches at the MMPP2 phase-transition
67% rates (-D0 diagonal minus the total arrival rate).
68envBase = buildCacheModel(n, m, pAccess1, pAccess2);
69env = Environment('MMPPphase');
70env.addStage('Phase1', 'bursty', local_setRates(envBase, D11(1,1), D12(1,1))); % 3.6/0.4
71env.addStage('Phase2', 'calm', local_setRates(envBase, D11(2,2), D12(2,2))); % 0.2/0.8
72env.addTransition('Phase1', 'Phase2', Exp(-D0(1,1) - (D11(1,1)+D12(1,1)))); % 0.5
73env.addTransition('Phase2', 'Phase1', Exp(-D0(2,2) - (D11(2,2)+D12(2,2)))); % 0.5
74env.init();
75env.getStageTable()
76
77solverFactory = @(mdl) CTMC(mdl, 'keep', false, 'cutoff', 1);
78
79% (3a) ENV method 'avg' - fast-environment limit (rate-averaged single model)
80optAvg = Solver.defaultOptions; optAvg.method = 'avg'; optAvg.verbose = false;
81solver{3} = ENV(env, solverFactory, optAvg);
82solver{3}.getAvg();
83hitAVG = solver{3}.ensemble{1}.getNodeByName('Cache').getHitRatio;
84
85% (3b) ENV method 'dec' - slow-environment quasi-stationary decomposition
86optDec = Solver.defaultOptions; optDec.method = 'dec'; optDec.verbose = false;
87solver{4} = ENV(env, solverFactory, optDec);
88solver{4}.getAvg();
89hitDEC = solver{4}.ensemble{1}.getNodeByName('Cache').getHitRatio;
90
91% (3c) ENV method 'blend' - state-vector coupling: carries the cache-state
92% distribution across phase switches and averages each phase's sojourn-weighted
93% distribution. Needs a finite-timespan CTMC inner solver.
94blendFactory = @(mdl) CTMC(mdl, 'keep', false, 'cutoff', 1, 'timespan', [0, 1e3]);
95optBlend = Solver.defaultOptions; optBlend.method = 'blend'; optBlend.verbose = false;
96optBlend.iter_max = 100; optBlend.iter_tol = 1e-4;
97solver{5} = ENV(env, blendFactory, optBlend);
98solver{5}.getAvg();
99hitBLEND = solver{5}.ensemble{1}.getNodeByName('Cache').getHitRatio;
100
101% (3d) ENV default mean-field with an FLD (refined mean-field) inner solver.
102% The cache is analyzed by the RMF drift; the mean occupancy is carried across
103% phase switches (the cache analog of the queue-length handoff) and the hit
104% ratio is the probEnv-weighted, sojourn-averaged (arrival x hit-prob). Needs a
105% finite-timespan fluid inner solver. This is the fully mean-field counterpart
106% of 'blend', trading the exact joint distribution for a fluid approximation.
107fldFactory = @(mdl) FLD(mdl, 'method', 'rmf', 'timespan', [0, 50]);
108optFLD = Solver.defaultOptions; optFLD.verbose = false;
109optFLD.iter_max = 100; optFLD.iter_tol = 1e-4;
110solver{6} = ENV(env, fldFactory, optFLD);
111solver{6}.getAvg();
112hitFLD = solver{6}.ensemble{1}.getNodeByName('Cache').getHitRatio;
113
114%% Summary: per-read-class actual hit ratio (classes 1=Read1, 2=Read2)
115fprintf('\n--- Actual cache hit ratio per read class ---\n');
116fprintf(' Read1 Read2\n');
117fprintf('LDES (sim) : %8.4f %8.4f\n', hitLDES(1), hitLDES(2));
118fprintf('CTMC (true) : %8.4f %8.4f\n', hitCTMC(1), hitCTMC(2));
119fprintf('ENV (avg) : %8.4f %8.4f\n', hitAVG(1), hitAVG(2));
120fprintf('ENV (dec) : %8.4f %8.4f\n', hitDEC(1), hitDEC(2));
121fprintf('ENV (blend) : %8.4f %8.4f\n', hitBLEND(1), hitBLEND(2));
122fprintf('ENV (mf/FLD) : %8.4f %8.4f\n', hitFLD(1), hitFLD(2));
123
124%% Local functions
125function model = buildCacheModel(n, m, pAccess1, pAccess2)
126 model = Network('MMAPCache');
127 source = Source(model, 'Source');
128 cacheNode = Cache(model, 'Cache', n, m, ReplacementStrategy.RR);
129 sink = Sink(model, 'Sink');
130
131 rd1 = OpenClass(model, 'Read1', 0);
132 rd2 = OpenClass(model, 'Read2', 0);
133 hit1 = OpenClass(model, 'Hit1', 0);
134 mis1 = OpenClass(model, 'Miss1', 0);
135 hit2 = OpenClass(model, 'Hit2', 0);
136 mis2 = OpenClass(model, 'Miss2', 0);
137
138 cacheNode.setRead(rd1, pAccess1);
139 cacheNode.setRead(rd2, pAccess2);
140 cacheNode.setHitClass(rd1, hit1); cacheNode.setMissClass(rd1, mis1);
141 cacheNode.setHitClass(rd2, hit2); cacheNode.setMissClass(rd2, mis2);
142
143 P = model.initRoutingMatrix;
144 P{rd1,rd1}(source, cacheNode) = 1.0;
145 P{rd2,rd2}(source, cacheNode) = 1.0;
146 P{hit1,hit1}(cacheNode, sink) = 1.0;
147 P{mis1,mis1}(cacheNode, sink) = 1.0;
148 P{hit2,hit2}(cacheNode, sink) = 1.0;
149 P{mis2,mis2}(cacheNode, sink) = 1.0;
150 model.link(P);
151end
152
153function model = local_setRates(baseModel, lambda1, lambda2)
154 model = baseModel.copy();
155 source = model.getNodeByName('Source');
156 source.setArrival(model.classes{1}, Exp(lambda1)); % Read1 Poisson
157 source.setArrival(model.classes{2}, Exp(lambda2)); % Read2 Poisson
158end
Definition Station.m:245