LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
solver_ssa_analyzer_serial.m
1function [XN,UN,QN,RN,TN,CN,tranSysState,tranSync,sn]=solver_ssa_analyzer_serial(sn, init_state, options, isHashed)
2% [XN,UN,QN,RN,TN,CN]=SOLVER_SSA_ANALYZER_SERIAL(SN, OPTIONS)
3
4M = sn.nstations; %number of stations
5K = sn.nclasses; %number of classes
6
7% istSpaceShift = zeros(1,M);
8% for i=1:M
9% if i==1
10% istSpaceShift(i) = 0;
11% else
12% istSpaceShift(i) = istSpaceShift(i-1) + size(sn.space{i-1},2);
13% end
14% end
15
16S = sn.nservers;
17NK = sn.njobs'; % initial population per class
18sched = sn.sched;
19Tstart = tic;
20
21PH = sn.proc;
22tranSysState = [];
23tranSync = [];
24
25XN = NaN*zeros(1,K);
26UN = NaN*zeros(M,K);
27QN = NaN*zeros(M,K);
28RN = NaN*zeros(M,K);
29TN = NaN*zeros(M,K);
30CN = NaN*zeros(1,K);
31
32
33if isfield(options,'config') && isfield(options.config,'eventcache')
34 eventCache = EventCache.create(options.config.eventcache, sn);
35else
36 eventCache = EventCache.create(false, sn);
37end
38
39% Snapshot the USER capacities before the solver_ssa preamble rewrites
40% sn.cap/classcap in place (it folds the state-space cutoff into them,
41% making every open class look capacity-constrained).
42userCap = sn.cap;
43userClasscap = sn.classcap;
44[probSysState,StateSpaceAggr,arvRates,depRates,tranSysState,tranSync] = solver_ssa(sn, init_state, options, eventCache);
45%%
46wset = 1:size(StateSpaceAggr,1);
47for k=1:K
48 refsf = sn.stationToStateful(sn.refstat(k));
49 XN(k) = probSysState*depRates(wset,refsf,k);
50end
51
52for ist=1:M
53 isf = sn.stationToStateful(ist);
54 for k=1:K
55 TN(ist,k) = probSysState*depRates(wset,isf,k);
56 QN(ist,k) = probSysState*StateSpaceAggr(wset,(ist-1)*K+k);
57 end
58 % For a USER-capacity-constrained OPEN class arrivals can be dropped, so
59 % the arrival-based estimator counts the OFFERED load (including dropped
60 % jobs) and overestimates utilization; use the departure-based (carried
61 % load) estimator for such a class. Closed classes are never dropped
62 % (their classcap is finite by population, not by a buffer), and the
63 % pre-preamble snapshot excludes the cutoff-derived truncation caps.
64 canDropClass = isinf(sn.njobs(:)') & (isfinite(userCap(ist)) | isfinite(userClasscap(ist,:)));
65 switch sched(ist)
66 case SchedStrategy.INF
67 for k=1:K
68 UN(ist,k) = QN(ist,k);
69 end
70 case {SchedStrategy.PS, SchedStrategy.DPS, SchedStrategy.GPS, ...
71 SchedStrategy.PSPRIO, SchedStrategy.DPSPRIO, SchedStrategy.GPSPRIO, SchedStrategy.LPS}
72 if isempty(sn.lldscaling) && isempty(sn.cdscaling)
73 for k=1:K
74 if ~isempty(PH{ist}{k})
75 if canDropClass(k)
76 UN(ist,k) = TN(ist,k)/sn.rates(ist,k)/S(ist);
77 else
78 UN(ist,k) = probSysState*arvRates(wset,isf,k)/sn.rates(ist,k)/S(ist);
79 end
80 end
81 end
82 else % lld/cd/ljd cases
83 ind = sn.stationToNode(ist);
84 % Busy-server FRACTION: carried load over the effective
85 % capacity. Load-dependent stations divide by the lldscaling
86 % peak; class-dependent stations divide by the declared
87 % per-class peak rate (sn.cdscalingpeak), so Util = T*S/peak.
88 isCd = ~isempty(sn.cdscaling) && ist <= numel(sn.cdscaling) && ~isempty(sn.cdscaling{ist});
89 ceff = S(ist);
90 if ~isempty(sn.lldscaling) && ist <= size(sn.lldscaling,1)
91 ceff = max(ceff, max(sn.lldscaling(ist,:)));
92 end
93 for k=1:K
94 if ~isempty(PH{ist}{k})
95 if isCd
96 cdiv = sn.cdscalingpeak(ist,k);
97 else
98 cdiv = ceff;
99 end
100 if cdiv > 0
101 UN(ist,k) = TN(ist,k)*map_mean(PH{ist}{k})/cdiv;
102 else
103 UN(ist,k) = 0;
104 end
105 end
106 end
107 % UN(i,1:K) = 0;
108 % for st = wset
109 % [ni,nir] = State.toMarginal(sn, ind, StateSpace(st,(istSpaceShift(i)+1):(istSpaceShift(i)+size(sn.space{i},2))));
110 % if ni>0
111 % for k=1:K
112 % UN(i,k) = UN(i,k) + probSysState(st)*nir(k)*sn.schedparam(i,k)/(nir*sn.schedparam(i,:)');
113 % end
114 % end
115 % end
116 end
117 otherwise
118 if isempty(sn.lldscaling) && isempty(sn.cdscaling)
119 for k=1:K
120 if ~isempty(PH{ist}{k})
121 if canDropClass(k)
122 UN(ist,k) = TN(ist,k)*map_mean(PH{ist}{k})/S(ist);
123 else
124 UN(ist,k) = probSysState*arvRates(wset,isf,k)*map_mean(PH{ist}{k})/S(ist);
125 end
126 end
127 end
128 else % lld/cd/ljd cases
129 ind = sn.stationToNode(ist);
130 % Busy-server FRACTION: carried load over the effective
131 % capacity. Load-dependent stations divide by the lldscaling
132 % peak; class-dependent stations divide by the declared
133 % per-class peak rate (sn.cdscalingpeak), so Util = T*S/peak.
134 isCd = ~isempty(sn.cdscaling) && ist <= numel(sn.cdscaling) && ~isempty(sn.cdscaling{ist});
135 ceff = S(ist);
136 if ~isempty(sn.lldscaling) && ist <= size(sn.lldscaling,1)
137 ceff = max(ceff, max(sn.lldscaling(ist,:)));
138 end
139 for k=1:K
140 if ~isempty(PH{ist}{k})
141 if isCd
142 cdiv = sn.cdscalingpeak(ist,k);
143 else
144 cdiv = ceff;
145 end
146 if cdiv > 0
147 UN(ist,k) = TN(ist,k)*map_mean(PH{ist}{k})/cdiv;
148 else
149 UN(ist,k) = 0;
150 end
151 end
152 end
153 % UN(i,1:K) = 0;
154 % for st = wset
155 % [ni,~,sir] = State.toMarginal(sn, ind, StateSpace(st,(istSpaceShift(i)+1):(istSpaceShift(i)+size(sn.space{i},2))));
156 % if ni>0
157 % for k=1:K
158 % UN(i,k) = UN(i,k) + probSysState(st)*sir(k)/S(i);
159 % end
160 % end
161 % end
162 end
163 end
164end
165
166for k=1:K
167 for ist=1:M
168 if TN(ist,k)>0
169 RN(ist,k) = QN(ist,k)./TN(ist,k);
170 else
171 RN(ist,k)=0;
172 end
173 end
174 CN(k) = NK(k)./XN(k);
175end
176%%
177
178% now update the routing probabilities in nodes with state-dependent routing
179TNcache = zeros(sn.nstateful, K);
180XNcache = zeros(sn.nstateful, K);
181for k=1:K
182 for isf=1:sn.nstateful
183 if sn.nodetype(isf) == NodeType.Cache
184 TNcache(isf,k) = probSysState*depRates(:,isf,k);
185 XNcache(isf,k) = probSysState*arvRates(:,isf,k);
186 end
187 end
188end
189
190% updates cache actual hit and miss data + retrieval-system expected latency.
191% For retrieval-aware caches, the per-class hit/miss accounting reads
192% TNcache for the configured hitClass / missClass (departures of those
193% classes downstream of the cache). The retrieval-complete arrival fires
194% the actual miss event in afterEventCache, so the miss-class departure
195% rate captured by TNcache is the true miss rate.
196retrievalLatencyWarned = false;
197for k=1:K
198 for isf=1:sn.nstateful
199 if sn.nodetype(isf) == NodeType.Cache
200 ind = sn.statefulToNode(isf);
201 np = sn.nodeparam{ind};
202 if length(np.hitclass)>=k
203 h = np.hitclass(k);
204 m = np.missclass(k);
205 if h>0 && m>0
206 sn.nodeparam{ind}.actualhitprob(k) = TNcache(isf,h)/sum(TNcache(isf,[h,m]));
207 sn.nodeparam{ind}.actualmissprob(k) = TNcache(isf,m)/sum(TNcache(isf,[h,m]));
208 else
209 sn.nodeparam{ind}.actualhitprob(k) = NaN;
210 sn.nodeparam{ind}.actualmissprob(k) = NaN;
211 end
212
213 % The Eq. 8 retrieval-system expected latency is not currently
214 % implemented; report NaN whenever a retrieval system is
215 % configured for this class.
216 expectedLatency = NaN;
217 if isfield(np, 'retrievalSystemQueueIndices') ...
218 && isKey(np.retrievalSystemQueueIndices, int32(k-1)) ...
219 && ~isempty(np.retrievalSystemQueueIndices(int32(k-1)))
220 if ~retrievalLatencyWarned
221 line_warning(mfilename, 'Retrieval-system expected latency is not currently implemented; reporting NaN.');
222 retrievalLatencyWarned = true;
223 end
224 end
225 sn.nodeparam{ind}.actualresidt(k) = expectedLatency;
226 end
227 end
228 end
229end
230
231QN(isnan(QN))=0;
232CN(isnan(CN))=0;
233RN(isnan(RN))=0;
234UN(isnan(UN))=0;
235XN(isnan(XN))=0;
236TN(isnan(TN))=0;
237end
Definition Station.m:245