aboutsummaryrefslogtreecommitdiffstats
path: root/native/src/blocking/linprog
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2013-01-29 07:47:01 -0500
committerBjoern Brandenburg <bbb@mpi-sws.org>2013-07-12 08:19:22 -0400
commit064f6a2915d8bcecea31f07b2a57de80203c6f37 (patch)
tree92ce02d07ba1779e434942616113f967c42d79ed /native/src/blocking/linprog
parente17645921697351bd968f034a85299c02332ad16 (diff)
Implement LP-based OMIP blocking analysis
Diffstat (limited to 'native/src/blocking/linprog')
-rw-r--r--native/src/blocking/linprog/lp_common.cpp34
-rw-r--r--native/src/blocking/linprog/lp_omip.cpp268
2 files changed, 302 insertions, 0 deletions
diff --git a/native/src/blocking/linprog/lp_common.cpp b/native/src/blocking/linprog/lp_common.cpp
index 1715d3b..2df1284 100644
--- a/native/src/blocking/linprog/lp_common.cpp
+++ b/native/src/blocking/linprog/lp_common.cpp
@@ -119,6 +119,40 @@ void set_blocking_objective_part_shm(
119 } 119 }
120} 120}
121 121
122// This version is for suspension-oblivious shared-memory protocols,
123// where the analysis does not differentiate among the different kinds
124// of blocking (since they are all just added to the execution time anyway).
125void set_blocking_objective_sob(
126 VarMapper& vars,
127 const ResourceSharingInfo& info,
128 const TaskInfo& ti,
129 LinearProgram& lp)
130{
131 LinearExpression *obj;
132
133 obj = lp.get_objective();
134
135 foreach_task_except(info.get_tasks(), ti, tx)
136 {
137 unsigned int t = tx->get_id();
138
139 foreach(tx->get_requests(), request)
140 {
141 unsigned int q = request->get_resource_id();
142 double length = request->get_request_length();;
143
144 foreach_request_instance(*request, ti, v)
145 {
146 unsigned int var_id;
147
148 var_id = vars.lookup(t, q, v, BLOCKING_SOB);
149 obj->add_term(length, var_id);
150 }
151 }
152 }
153}
154
155
122// Constraint 1 in [Brandenburg 2013] 156// Constraint 1 in [Brandenburg 2013]
123void add_mutex_constraints( 157void add_mutex_constraints(
124 VarMapper& vars, 158 VarMapper& vars,
diff --git a/native/src/blocking/linprog/lp_omip.cpp b/native/src/blocking/linprog/lp_omip.cpp
new file mode 100644
index 0000000..0e5d864
--- /dev/null
+++ b/native/src/blocking/linprog/lp_omip.cpp
@@ -0,0 +1,268 @@
1#include <iostream>
2#include <set>
3#include <algorithm>
4#include <cmath>
5
6#include "lp_common.h"
7#include "blocking.h"
8#include "stl-hashmap.h"
9
10#include "cpu_time.h"
11
12// Per-cluster, per-resource access counts.
13typedef hashmap<unsigned int, unsigned int> AccessCounts;
14typedef hashmap<unsigned int, AccessCounts> PerClusterACounts;
15
16static AccessCounts count_accesses(
17 const ResourceSharingInfo& info,
18 unsigned int cluster)
19{
20 AccessCounts acount;
21
22 foreach(info.get_tasks(), tx) {
23 if (tx->get_cluster() == cluster) {
24 foreach(tx->get_requests(), request)
25 {
26 unsigned int q = request->get_resource_id();
27 // count that q is being accessed by tx
28 acount[q] += 1;
29 }
30 }
31 }
32 return acount;
33}
34
35static void add_total_constraints(
36 VarMapper& vars,
37 const ResourceSharingInfo& info,
38 const TaskInfo& ti,
39 LinearProgram& lp,
40 unsigned int num_procs)
41{
42 // one constraint for each resource
43 hashmap<unsigned int, LinearExpression *> constraints;
44 LinearExpression *exp;
45
46 foreach_task_except(info.get_tasks(), ti, tx)
47 {
48 unsigned int t = tx->get_id();
49
50 //for all requests accessed by tx
51 foreach(tx->get_requests(), request)
52 {
53 unsigned int q = request->get_resource_id();
54
55 if (constraints.find(q) == constraints.end())
56 constraints[q] = new LinearExpression();
57 exp = constraints[q];
58 foreach_request_instance(*request, ti, v)
59 {
60 unsigned int var_id;
61 var_id = vars.lookup(t, q, v, BLOCKING_SOB);
62 exp->add_var(var_id);
63 }
64 }
65 }
66
67 // add each per-resource constraint
68 foreach(constraints, it) {
69 unsigned int bound = ti.get_num_requests(it->first);
70 bound *= (2 * num_procs - 1);
71 lp.add_inequality(it->second, bound);
72 }
73}
74
75
76static void add_remote_cluster_constraints(
77 VarMapper& vars,
78 const ResourceSharingInfo& info,
79 const TaskInfo& ti,
80 LinearProgram& lp,
81 AccessCounts& acount,
82 unsigned int num_procs,
83 unsigned int cluster_size)
84{
85 // one constraint for each cluster and each resource
86 hashmap<unsigned int, hashmap<unsigned int, LinearExpression *> > cluster_c;
87 LinearExpression *exp;
88
89 foreach_remote_task(info.get_tasks(), ti, tx)
90 {
91 unsigned int t = tx->get_id();
92 unsigned int c = tx->get_cluster();
93
94 hashmap<unsigned int, LinearExpression *> &constraints = cluster_c[c];
95
96 //for all requests accessed by tx
97 foreach(tx->get_requests(), request)
98 {
99 unsigned int q = request->get_resource_id();
100
101 if (constraints.find(q) == constraints.end())
102 constraints[q] = new LinearExpression();
103 exp = constraints[q];
104
105 foreach_request_instance(*request, ti, v)
106 {
107 unsigned int var_id;
108 var_id = vars.lookup(t, q, v, BLOCKING_SOB);
109 exp->add_var(var_id);
110 }
111 }
112 }
113
114 // add each per-resource constraint
115 foreach(cluster_c, ct) {
116 assert(ct->first != ti.get_cluster());
117 foreach(ct->second, it) {
118 unsigned int bound = ti.get_num_requests(it->first);
119 unsigned int q = it->first;
120 if (acount[q] <= 2 * cluster_size) {
121 // FQ-only case
122 bound *= acount[q];
123 } else {
124 // PQ case
125 bound *= (cluster_size + num_procs);
126 }
127 lp.add_inequality(it->second, bound);
128 }
129 }
130}
131
132static void add_local_cluster_constraints(
133 VarMapper& vars,
134 const ResourceSharingInfo& info,
135 const TaskInfo& ti,
136 LinearProgram& lp,
137 AccessCounts& acount,
138 unsigned int cluster_size)
139{
140 foreach_local_task_except(info.get_tasks(), ti, tx)
141 {
142 unsigned int t = tx->get_id();
143 //for all requests accessed by tx
144 foreach(tx->get_requests(), request)
145 {
146 unsigned int q = request->get_resource_id();
147 LinearExpression *exp = new LinearExpression();
148
149 foreach_request_instance(*request, ti, v)
150 {
151 unsigned int var_id;
152 var_id = vars.lookup(t, q, v, BLOCKING_SOB);
153 exp->add_var(var_id);
154 }
155 unsigned int bound = ti.get_num_requests(q);
156 if (acount[q] > 2 * cluster_size)
157 bound *= 2; // PQ case
158 lp.add_inequality(exp, bound);
159 }
160 }
161}
162
163
164static void add_omip_constraints(
165 VarMapper& vars,
166 const ResourceSharingInfo& info,
167 const TaskInfo& ti,
168 LinearProgram& lp,
169 AccessCounts& acounts,
170 unsigned int num_procs,
171 unsigned int cluster_size)
172{
173 add_total_constraints(vars, info, ti, lp, num_procs);
174 add_remote_cluster_constraints(vars, info, ti, lp, acounts, num_procs, cluster_size);
175 add_local_cluster_constraints(vars, info, ti, lp, acounts, num_procs);
176}
177
178static void apply_omip_bounds_for_task(
179 unsigned int i,
180 BlockingBounds& bounds,
181 const ResourceSharingInfo& info,
182 PerClusterACounts &pcacounts,
183 unsigned int num_procs,
184 unsigned int cluster_size)
185{
186 LinearProgram lp;
187 VarMapper vars;
188 const TaskInfo& ti = info.get_tasks()[i];
189 unsigned int cluster = ti.get_cluster();
190
191 if (pcacounts.find(cluster) == pcacounts.end())
192 pcacounts[cluster] = count_accesses(info, cluster);
193
194#if DEBUG_LP_OVERHEADS >= 2
195 static DEFINE_CPU_CLOCK(model_gen_cost);
196 static DEFINE_CPU_CLOCK(solver_cost);
197
198 std::cout << "---- " << __FUNCTION__ << " ----" << std::endl;
199
200 model_gen_cost.start();
201#endif
202
203 set_blocking_objective_sob(vars, info, ti, lp);
204 vars.seal();
205
206 add_omip_constraints(vars, info, ti, lp,
207 pcacounts[cluster], num_procs, cluster_size);
208
209#if DEBUG_LP_OVERHEADS >= 2
210 model_gen_cost.stop();
211 std::cout << model_gen_cost << std::endl;
212 solver_cost.start();
213#endif
214
215 Solution *sol = linprog_solve(lp, vars.get_num_vars());
216
217#if DEBUG_LP_OVERHEADS >= 2
218 solver_cost.stop();
219 std::cout << solver_cost << std::endl;
220#endif
221 assert(sol != NULL);
222
223 Interference total;
224
225 total.total_length = lrint(sol->evaluate(*lp.get_objective()));
226 bounds[i] = total;
227
228 delete sol;
229}
230
231
232static BlockingBounds* _lp_omip_bounds(
233 const ResourceSharingInfo& info,
234 unsigned int num_procs,
235 unsigned int cluster_size)
236{
237 PerClusterACounts pcacounts;
238 BlockingBounds* results = new BlockingBounds(info);
239
240 for (unsigned int i = 0; i < info.get_tasks().size(); i++)
241 apply_omip_bounds_for_task(i, *results, info, pcacounts, num_procs, cluster_size);
242
243 return results;
244}
245
246BlockingBounds* lp_omip_bounds(
247 const ResourceSharingInfo& info,
248 unsigned int num_procs,
249 unsigned int cluster_size)
250{
251 assert(num_procs >= cluster_size);
252 assert(num_procs % cluster_size == 0);
253
254#if DEBUG_LP_OVERHEADS >= 1
255 static DEFINE_CPU_CLOCK(cpu_costs);
256
257 cpu_costs.start();
258#endif
259
260 BlockingBounds *results = _lp_omip_bounds(info, num_procs, cluster_size);
261
262#if DEBUG_LP_OVERHEADS >= 1
263 cpu_costs.stop();
264 std::cout << cpu_costs << std::endl;
265#endif
266
267 return results;
268}