diff options
author | Andrii Anisov <andrii_anisov@epam.com> | 2017-08-31 10:14:24 -0400 |
---|---|---|
committer | Björn Brandenburg <bbb@mpi-sws.org> | 2017-09-08 12:03:42 -0400 |
commit | ce8aeb80262d60cdfe762931f6c71e2b5ab22ef7 (patch) | |
tree | 6124bbcb9f4c3ab2b0821ed32c26e72172b07cb7 | |
parent | 35bb1bae9d010ebbb6737d6238b3d5971c0506fc (diff) |
Introduce a task configuration based on amount of work
In order to make experiments in virtualized environment it is
introduced a task (rtspin) configuration based on amount of work.
Though this configuration requires some manual operation for choosing
number of cycles burned for 1ms of task execution.
First you need to run 'rtspin -A' baremetal or on a virtualized
environment with pinned CPUs with 100% bandwidth and take a cycles number
for 1ms taks. Optionally verify chosen number with 'rtspin -l -a CYCLES'.
Then use the number for workload runs.
Signed-off-by: Andrii Anisov <andrii_anisov@epam.com>
-rw-r--r-- | bin/rtspin.c | 133 |
1 files changed, 105 insertions, 28 deletions
diff --git a/bin/rtspin.c b/bin/rtspin.c index 8a25af2..c69f3e4 100644 --- a/bin/rtspin.c +++ b/bin/rtspin.c | |||
@@ -19,8 +19,9 @@ const char *usage_msg = | |||
19 | "Usage: (1) rtspin OPTIONS WCET PERIOD DURATION\n" | 19 | "Usage: (1) rtspin OPTIONS WCET PERIOD DURATION\n" |
20 | " (2) rtspin -S [INPUT] WCET PERIOD DURATION\n" | 20 | " (2) rtspin -S [INPUT] WCET PERIOD DURATION\n" |
21 | " (3) rtspin OPTIONS -F FILE [-C COLUMN] WCET PERIOD [DURATION]\n" | 21 | " (3) rtspin OPTIONS -F FILE [-C COLUMN] WCET PERIOD [DURATION]\n" |
22 | " (4) rtspin -l\n" | 22 | " (4) rtspin -l [-a CYCLES]\n" |
23 | " (5) rtspin -B -m FOOTPRINT\n" | 23 | " (5) rtspin -B -m FOOTPRINT\n" |
24 | " (6) rtspin -A\n" | ||
24 | "\n" | 25 | "\n" |
25 | "Modes: (1) run as periodic task with given WCET and PERIOD\n" | 26 | "Modes: (1) run as periodic task with given WCET and PERIOD\n" |
26 | " (2) run as sporadic task with given WCET and PERIOD,\n" | 27 | " (2) run as sporadic task with given WCET and PERIOD,\n" |
@@ -31,12 +32,15 @@ const char *usage_msg = | |||
31 | " (4) Run calibration loop (how accurately are target\n" | 32 | " (4) Run calibration loop (how accurately are target\n" |
32 | " runtimes met?)\n" | 33 | " runtimes met?)\n" |
33 | " (5) Run background, non-real-time cache-thrashing loop.\n" | 34 | " (5) Run background, non-real-time cache-thrashing loop.\n" |
35 | " (6) Run 1 ms workload calibration (estimate cycles for 1ms, 10ms, 100ms workload)\n" | ||
34 | "\n" | 36 | "\n" |
35 | "Required arguments:\n" | 37 | "Required arguments:\n" |
36 | " WCET, PERIOD reservation parameters (in ms)\n" | 38 | " WCET, PERIOD reservation parameters (in ms)\n" |
37 | " DURATION terminate the task after DURATION seconds\n" | 39 | " DURATION terminate the task after DURATION seconds\n" |
38 | "\n" | 40 | "\n" |
39 | "Options:\n" | 41 | "Options:\n" |
42 | " -A calibrate 1ms workload cycles\n" | ||
43 | " -a CYCLES number of cycles for 1ms of workload loop chosen after calibration\n " | ||
40 | " -B run non-real-time background loop\n" | 44 | " -B run non-real-time background loop\n" |
41 | " -c be|srt|hrt task class (best-effort, soft real-time, hard real-time)\n" | 45 | " -c be|srt|hrt task class (best-effort, soft real-time, hard real-time)\n" |
42 | " -d DEADLINE relative deadline, equal to the period by default (in ms)\n" | 46 | " -d DEADLINE relative deadline, equal to the period by default (in ms)\n" |
@@ -165,18 +169,23 @@ static int nr_of_pages = 0; | |||
165 | static int page_size; | 169 | static int page_size; |
166 | static void *base = NULL; | 170 | static void *base = NULL; |
167 | 171 | ||
168 | static int loop_once(void) | 172 | static int cycles_ms = 0; |
173 | |||
174 | static int loop(int count) | ||
169 | { | 175 | { |
170 | int i, j = 0; | 176 | int i, j = 0; |
171 | /* touch some numbers and do some math */ | 177 | /* touch some numbers and do some math */ |
172 | for (i = 0; i < NUMS; i++) { | 178 | for (i = 0; i < count; i++) { |
173 | j += num[i]++; | 179 | int index = i % NUMS; |
174 | if (j > num[i]) | 180 | j += num[index]++; |
175 | num[i] = (j / 2) + 1; | 181 | if (j > num[index]) |
182 | num[index] = (j / 2) + 1; | ||
176 | } | 183 | } |
177 | return j; | 184 | return j; |
178 | } | 185 | } |
179 | 186 | ||
187 | #define loop_once() loop(NUMS) | ||
188 | |||
180 | static int loop_once_with_mem(void) | 189 | static int loop_once_with_mem(void) |
181 | { | 190 | { |
182 | int i, j = 0; | 191 | int i, j = 0; |
@@ -202,30 +211,35 @@ static int loop_once_with_mem(void) | |||
202 | 211 | ||
203 | static int loop_for(double exec_time, double emergency_exit) | 212 | static int loop_for(double exec_time, double emergency_exit) |
204 | { | 213 | { |
205 | double last_loop = 0, loop_start; | ||
206 | int tmp = 0; | 214 | int tmp = 0; |
207 | 215 | ||
208 | double start = cputime(); | 216 | if (cycles_ms) { |
209 | double now = cputime(); | 217 | double count = cycles_ms * exec_time * 1000; |
218 | tmp += loop(count); | ||
219 | } else { | ||
220 | double last_loop = 0, loop_start; | ||
221 | double start = cputime(); | ||
222 | double now = cputime(); | ||
210 | 223 | ||
211 | while (now + last_loop < start + exec_time) { | 224 | while (now + last_loop < start + exec_time) { |
212 | loop_start = now; | 225 | loop_start = now; |
213 | if (nr_of_pages) | 226 | if (nr_of_pages) |
214 | tmp += loop_once_with_mem(); | 227 | tmp += loop_once_with_mem(); |
215 | else | 228 | else |
216 | tmp += loop_once(); | 229 | tmp += loop_once(); |
217 | now = cputime(); | 230 | now = cputime(); |
218 | last_loop = now - loop_start; | 231 | last_loop = now - loop_start; |
219 | if (emergency_exit && wctime() > emergency_exit) { | 232 | if (emergency_exit && wctime() > emergency_exit) { |
220 | /* Oops --- this should only be possible if the | 233 | /* Oops --- this should only be possible if the |
221 | * execution time tracking is broken in the LITMUS^RT | 234 | * execution time tracking is broken in the LITMUS^RT |
222 | * kernel or the user specified infeasible parameters. | 235 | * kernel or the user specified infeasible parameters. |
223 | */ | 236 | */ |
224 | fprintf(stderr, "!!! rtspin/%d emergency exit!\n", | 237 | fprintf(stderr, "!!! rtspin/%d emergency exit!\n", |
225 | getpid()); | 238 | getpid()); |
226 | fprintf(stderr, "Reached experiment timeout while " | 239 | fprintf(stderr, "Reached experiment timeout while " |
227 | "spinning.\n"); | 240 | "spinning.\n"); |
228 | break; | 241 | break; |
242 | } | ||
229 | } | 243 | } |
230 | } | 244 | } |
231 | 245 | ||
@@ -251,6 +265,51 @@ static void debug_delay_loop(void) | |||
251 | } | 265 | } |
252 | } | 266 | } |
253 | 267 | ||
268 | static int calibrate_ms(int ms) | ||
269 | { | ||
270 | int right = NUMS; | ||
271 | int left = 0; | ||
272 | int middle; | ||
273 | |||
274 | double start; | ||
275 | double now; | ||
276 | double dms = 0.001 * ms; | ||
277 | |||
278 | /*look for initial loop count values for binary search*/ | ||
279 | for (;;) | ||
280 | { | ||
281 | printf("Probe %d loops for %d ms:\n", right, ms); | ||
282 | start = wctime(); | ||
283 | loop(right); | ||
284 | now = wctime(); | ||
285 | if ((now - start) >= dms) | ||
286 | break; | ||
287 | left = right; | ||
288 | right += right; | ||
289 | } | ||
290 | |||
291 | middle = (left + right) / 2; | ||
292 | |||
293 | /*binary search for a loop count value for expected calibration time*/ | ||
294 | while (left < middle) | ||
295 | { | ||
296 | start = wctime(); | ||
297 | loop(middle); | ||
298 | now = wctime(); | ||
299 | |||
300 | printf("%d loops elapsed in %4.20f s\n", middle, now - start); | ||
301 | |||
302 | if ((now - start) < dms) | ||
303 | left = middle; | ||
304 | else if ((now - start) == dms) | ||
305 | return middle; | ||
306 | else | ||
307 | right = middle; | ||
308 | middle = (left + right) / 2; | ||
309 | } | ||
310 | return middle; | ||
311 | } | ||
312 | |||
254 | static int wait_for_input(int event_fd) | 313 | static int wait_for_input(int event_fd) |
255 | { | 314 | { |
256 | /* We do a blocking read, accepting up to 4KiB of data. | 315 | /* We do a blocking read, accepting up to 4KiB of data. |
@@ -297,7 +356,7 @@ static void job(double exec_time, double program_end, int lock_od, double cs_len | |||
297 | } | 356 | } |
298 | } | 357 | } |
299 | 358 | ||
300 | #define OPTSTR "p:c:wlveo:F:s:m:q:r:X:L:Q:iRu:U:Bhd:C:S::TD:E:" | 359 | #define OPTSTR "p:c:Awlveo:F:s:m:q:r:X:L:Q:iRu:U:Bhd:C:S::TD:E:a:" |
301 | 360 | ||
302 | int main(int argc, char** argv) | 361 | int main(int argc, char** argv) |
303 | { | 362 | { |
@@ -318,6 +377,7 @@ int main(int argc, char** argv) | |||
318 | int opt; | 377 | int opt; |
319 | int wait = 0; | 378 | int wait = 0; |
320 | int test_loop = 0; | 379 | int test_loop = 0; |
380 | int caliber_ms = 0; | ||
321 | int background_loop = 0; | 381 | int background_loop = 0; |
322 | int column = 1; | 382 | int column = 1; |
323 | const char *file = NULL; | 383 | const char *file = NULL; |
@@ -462,6 +522,12 @@ int main(int argc, char** argv) | |||
462 | verbose = 1; | 522 | verbose = 1; |
463 | report_interrupts = 1; | 523 | report_interrupts = 1; |
464 | break; | 524 | break; |
525 | case 'A': | ||
526 | caliber_ms = 1; | ||
527 | break; | ||
528 | case 'a': | ||
529 | cycles_ms = want_non_negative_int(optarg, "-a"); | ||
530 | break; | ||
465 | case ':': | 531 | case ':': |
466 | usage("Argument missing."); | 532 | usage("Argument missing."); |
467 | break; | 533 | break; |
@@ -495,10 +561,21 @@ int main(int argc, char** argv) | |||
495 | srand(getpid()); | 561 | srand(getpid()); |
496 | 562 | ||
497 | if (test_loop) { | 563 | if (test_loop) { |
564 | if (cycles_ms > 0) | ||
565 | printf("Evaluating loop with %d cycles:\n", cycles_ms); | ||
566 | |||
498 | debug_delay_loop(); | 567 | debug_delay_loop(); |
499 | return 0; | 568 | return 0; |
500 | } | 569 | } |
501 | 570 | ||
571 | if (caliber_ms) { | ||
572 | printf("In 1 ms %d loops\n", calibrate_ms(1)); | ||
573 | printf("In 10 ms %d loops\n", calibrate_ms(10)); | ||
574 | printf("In 100 ms %d loops\n", calibrate_ms(100)); | ||
575 | printf("In 1 s %d loops\n", calibrate_ms(1000)); | ||
576 | return 0; | ||
577 | } | ||
578 | |||
502 | if (background_loop) { | 579 | if (background_loop) { |
503 | while (1) { | 580 | while (1) { |
504 | if (nr_of_pages) | 581 | if (nr_of_pages) |