LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
lqn_boxbounds.m
1%{
2 % @brief Majumdar-Woodside robust box bounds on throughput for a layered
3 % queueing network (LQN), computed on the processor-contention model.
4 %
5 % @details
6 % Builds a closed multiclass queueing network from a LayeredNetworkStruct in
7 % which the stations are the processors (hosts) and the classes are the
8 % reference-task call chains, then applies the Majumdar-Woodside robust box
9 % bounds (see pfqn_mwrbb). The per-chain demand at each processor is the total
10 % host demand executed on that processor during one cycle of the reference
11 % task, obtained by traversing the activity/call graph and scaling by the
12 % mean number of synchronous calls. The reference-task multiplicity is the
13 % class population and the reference-task think time is the class think time.
14 %
15 % This generalizes the classical LQN "Type 1 throughput bound"
16 % X_ref <= mult/(Z + D_total) (the no-contention upper bound, as computed by
17 % lqns -b) by additionally providing the processor-utilization upper bound and
18 % the Majumdar-Woodside lower bound (throughput guarantee, Theorem 2).
19 %
20 % Scope: processors are the queueing resources; reference-task chains are the
21 % classes. Software (finite-thread task) bottlenecks and non-deterministic
22 % activity precedence (OR-branch probabilities, loop repetitions) are not
23 % modeled here (sequential activity execution is assumed).
24 %
25 % @par Syntax:
26 % @code
27 % out = lqn_boxbounds(lqn)
28 % @endcode
29 %
30 % @par Parameters:
31 % <table>
32 % <tr><th>Name<th>Description
33 % <tr><td>lqn<td>LayeredNetworkStruct (from LayeredNetwork.getStruct())
34 % </table>
35 %
36 % @par Returns (struct out):
37 % <table>
38 % <tr><th>Field<th>Description
39 % <tr><td>refidx<td>(1 x R) absolute indices of the reference tasks
40 % <tr><td>Xlo,Xup<td>(1 x R) lower/upper throughput bound per reference chain
41 % <tr><td>TN_lo,TN_up<td>(nidx x 1) throughput bound propagated to all elements
42 % <tr><td>UN_lo,UN_up<td>(nidx x 1) processor utilization bound (util law)
43 % <tr><td>D<td>(nhosts x R) per-chain demand at each processor
44 % </table>
45%}
46function out = lqn_boxbounds(lqn)
47nidx = lqn.nidx;
48nH = lqn.nhosts;
49
50% reference tasks -> classes
51refidx = [];
52for t = 1:lqn.ntasks
53 tidx = lqn.tshift + t;
54 if lqn.isref(tidx)
55 refidx(end+1) = tidx; %#ok<AGROW>
56 end
57end
58R = numel(refidx);
59
60D = zeros(nH, R);
61Vis = zeros(nidx, R);
62Nref = zeros(1, R);
63Zref = zeros(1, R);
64for r = 1:R
65 tidx = refidx(r);
66 Nref(r) = lqn.mult(tidx);
67 if isinf(Nref(r)), Nref(r) = 1; end % open/infinite ref treated as 1
68 z = lqn.think_mean(tidx);
69 if isnan(z), z = 0; end
70 Zref(r) = z;
71 for eidx = lqn.entriesof{tidx}
72 [D(:,r), Vis(:,r)] = visitEntry(lqn, eidx, 1.0, nH, D(:,r), Vis(:,r));
73 end
74end
75
76% processor scheduling -> discipline code; equal class priority
77schedH = zeros(nH, 1);
78for h = 1:nH
79 schedH(h) = discCode(lqn.sched(h));
80end
81prio = zeros(1, R);
82
83V = double(D > 0);
84S = D;
85[Xlo, Xup] = pfqn_mwrbb(V, S, Nref, Zref, schedH, prio);
86
87% propagate to all LQN elements
88TN_lo = nan(nidx, 1); TN_up = nan(nidx, 1);
89UN_lo = nan(nidx, 1); UN_up = nan(nidx, 1);
90for idx = 1:nidx
91 if any(Vis(idx, :) > 0)
92 TN_lo(idx) = sum(Xlo .* Vis(idx, :));
93 TN_up(idx) = sum(Xup .* Vis(idx, :));
94 end
95end
96for h = 1:nH
97 UN_lo(h) = sum(Xlo .* D(h, :));
98 UN_up(h) = sum(Xup .* D(h, :));
99end
100
101out = struct('refidx', refidx, 'Xlo', Xlo, 'Xup', Xup, ...
102 'TN_lo', TN_lo, 'TN_up', TN_up, 'UN_lo', UN_lo, 'UN_up', UN_up, 'D', D);
103end
104
105% ------------------------------------------------------------------------
106function [d, vis] = visitEntry(lqn, eidx, mult, nH, d, vis)
107vis(eidx) = vis(eidx) + mult;
108tidx = lqn.parent(eidx); % task hosting this entry
109if tidx >= 1 && tidx <= numel(vis)
110 vis(tidx) = vis(tidx) + mult;
111end
112acts = lqn.actsof{eidx};
113for aidx = acts
114 if lqn.parent(aidx) == lqn.parent(eidx) % activity of this entry
115 [d, vis] = visitActivity(lqn, aidx, mult, nH, d, vis);
116 end
117end
118end
119
120function [d, vis] = visitActivity(lqn, aidx, mult, nH, d, vis)
121vis(aidx) = vis(aidx) + mult;
122tidx = lqn.parent(aidx);
123hidx = lqn.parent(tidx); % host absolute index (hshift=0)
124hd = lqn.hostdem_mean(aidx);
125if isnan(hd), hd = 0; end
126if hidx >= 1 && hidx <= nH
127 d(hidx) = d(hidx) + mult * hd;
128end
129for cidx = lqn.callsof{aidx}
130 if lqn.calltype(cidx) == CallType.SYNC
131 cmean = lqn.callproc_mean(cidx);
132 callee = lqn.callpair(cidx, 2);
133 [d, vis] = visitEntry(lqn, callee, mult * cmean, nH, d, vis);
134 end
135end
136end
137
138% Map a SchedStrategy id to a Majumdar-Woodside discipline code:
139% 0=FIFO, 1=PS, 2=non-preemptive priority, 3=preemptive priority,
140% 4=ABA full-contention (discipline-independent).
141function code = discCode(s)
142switch s
143 case {SchedStrategy.FCFS}
144 code = 0;
145 case {SchedStrategy.PS, SchedStrategy.DPS, SchedStrategy.GPS, ...
146 SchedStrategy.PSPRIO, SchedStrategy.DPSPRIO, SchedStrategy.GPSPRIO}
147 code = 1;
148 case {SchedStrategy.HOL}
149 code = 2;
150 case {SchedStrategy.FCFSPRPRIO, SchedStrategy.LCFSPRPRIO}
151 code = 3;
152 otherwise
153 code = 4;
154end
155end
Definition Station.m:245