diff options
-rw-r--r-- | README | 507 |
1 files changed, 507 insertions, 0 deletions
@@ -0,0 +1,507 @@ | |||
1 | I. INTRODUCTION | ||
2 | These scripts provide a common way for creating, running, parsing, and | ||
3 | plotting experiments under LITMUS^RT. They are designed with the | ||
4 | following principles in mind: | ||
5 | |||
6 | 1. Little or no configuration: all scripts use certain parameters to | ||
7 | configure behavior. However, if the user does not give these | ||
8 | parameters, the scripts will examine the properties of the user's | ||
9 | system to pick a suitable default. Requiring user input is a last | ||
10 | resort. | ||
11 | |||
12 | 2. Interruptability: the scripts save their work as they evaluate | ||
13 | multiple directories. When the scripts are interrupted, or if new data | ||
14 | is added to those directories, the scripts can be re-run and they will | ||
15 | resume where they left off. This vastly decreases turnaround time for | ||
16 | testing new features. | ||
17 | |||
18 | 3. Maximum Safety: where possible, scripts save metadata in their output | ||
19 | directories about the data contained. This metadata can be used by | ||
20 | the other scripts to safely use the data later. | ||
21 | |||
22 | 4. Independence / legacy support: none of these scripts assume their | ||
23 | input was generated by another of these scripts. Three are designed to | ||
24 | recognize generic input formats inspired by past LITMUS^RT | ||
25 | experimental setups. (The exception to this is gen_exps.py, which | ||
26 | has only user intput and creates output only for run_exps.py) | ||
27 | |||
28 | 5. Save everything: all output and parameters (even from subprocesses) | ||
29 | is saved for debugging / reproducability. This data is saved in tmp/ | ||
30 | directories while scripts are running in case scripts fail. | ||
31 | |||
32 | These scripts require that the following repos are in the user's PATH: | ||
33 | 1. liblitmus - for real-time executable simulation and task set release | ||
34 | 2. feather-trace-tools - for recording and parsing overheads and | ||
35 | scheduling events | ||
36 | |||
37 | Optionally, additional features will be enabled if these repos are | ||
38 | present in the PATH: | ||
39 | 1. rt-kernelshark - to record ftrace events for kernelshark visualization | ||
40 | 2. sched_trace - to output a file containing scheduling events as | ||
41 | strings | ||
42 | |||
43 | Each of these scripts is designed to operate independently of the | ||
44 | others. For example, the parse_exps.py will find any feather trace | ||
45 | files resembling ft-xyz.bin or xyz.ft and print out overhead | ||
46 | statistics for the records inside. However, the scripts provide the | ||
47 | most features (especially safety) when their results are chained | ||
48 | together, like so: | ||
49 | |||
50 | gen_exps.py --> [exps/*] --> run_exps.py --> [run-data/*] --. | ||
51 | .------------------------------------------------------------' | ||
52 | '--> parse_exps.py --> [parse-data/*] --> plot_exps.py --> [plot-data/*.pdf] | ||
53 | |||
54 | 0. Create experiments with gen_exps.py or some other script. | ||
55 | 1. Run experiments using run_exps.py, generating binary files in run-data/. | ||
56 | 2. Parse binary data in run-data using parse_exps.py, generating csv | ||
57 | files in parse-data/. | ||
58 | 3. Plot parse-data using plot_exps.py, generating pdfs in plot-data. | ||
59 | |||
60 | Each of these scripts will be described. The run_exps.py script is | ||
61 | first because gen_exps.py creates schedule files which depend on run_exps.py. | ||
62 | |||
63 | |||
64 | II. RUN_EXPS | ||
65 | Usage: run_exps.py [OPTIONS] [SCHED_FILE]... [SCHED_DIR]... | ||
66 | where a SCHED_DIR resembles: | ||
67 | SCHED_DIR/ | ||
68 | SCHED_FILE | ||
69 | PARAM_FILE | ||
70 | |||
71 | Output: OUT_DIR/[files] or OUT_DIR/SCHED_DIR/[files] or | ||
72 | OUT_DIR/SCHED_FILE/[files] depending on input | ||
73 | If all features are enabled, these files are: | ||
74 | OUT_DIR/[.*/] | ||
75 | trace.slog # LITMUS logging | ||
76 | st-[1..m].bin # sched_trace data | ||
77 | ft.bin # feather-trace overhead data | ||
78 | trace.dat # ftrace data for kernelshark | ||
79 | params.py # Schedule parameters | ||
80 | exec-out.txt # Standard out from schedule processes | ||
81 | exec-err.txt # Standard err ''' | ||
82 | |||
83 | Defaults: SCHED_FILE = sched.py, PARAM_FILE = params.py, | ||
84 | DURATION = 30, OUT_DIR = run-data/ | ||
85 | |||
86 | The run_exps.py script reads schedule files and executes real-time | ||
87 | task systems, recording all overhead, logging, and trace data which is | ||
88 | enabled in the system. For example, if trace logging is enabled, | ||
89 | rt-kernelshark is found in the path, but feather-trace is disabled | ||
90 | (the devices are not present), only trace-logs and kernelshark logs | ||
91 | will be recorded. | ||
92 | |||
93 | When run_exps.py is running a schedule file, temporary data is saved | ||
94 | in a 'tmp' directory in the same directory as the schedule file. When | ||
95 | execution completes, this data is moved into a directory under the | ||
96 | run_exps.py output directory (default: 'run-data/', can be changed with | ||
97 | the -o option). When multiple schedules are run, each schedule's data | ||
98 | is saved in a unique directory under the output directory. | ||
99 | |||
100 | If a schedule has been run and it's data is in the output directory, | ||
101 | run_exps.py will not re-run the schedule unless the -f option is | ||
102 | specified. This is useful if your system crashes midway through a set | ||
103 | of experiments. | ||
104 | |||
105 | Schedule files have one of the following two formats: | ||
106 | |||
107 | a) simple format | ||
108 | path/to/proc{proc_value} | ||
109 | ... | ||
110 | path/to/proc{proc_value} | ||
111 | [real_time_task: default rtspin] task_arguments... | ||
112 | ... | ||
113 | [real_time_task] task_arguments... | ||
114 | |||
115 | b) python format | ||
116 | {'proc':[ | ||
117 | ('path/to/proc','proc_value'), | ||
118 | ..., | ||
119 | ('path/to/proc','proc_value') | ||
120 | ], | ||
121 | 'spin':[ | ||
122 | ('real_time_task', 'task_arguments'), | ||
123 | ... | ||
124 | ('real_time_task', 'task_arguments') | ||
125 | ] | ||
126 | } | ||
127 | |||
128 | The following creates a simple 3-task system with utilization 2.0, | ||
129 | which is then run under the GSN-EDF plugin: | ||
130 | |||
131 | $ echo "10 20 | ||
132 | 30 40 | ||
133 | 60 90" > test.sched | ||
134 | $ run_exps.py -s GSN-EDF test.sched | ||
135 | |||
136 | The following will write a release master using | ||
137 | /proc/litmus/release_master: | ||
138 | |||
139 | $ echo "release_master{2} | ||
140 | 10 20" > test.sched && run_exps.py -s GSN-EDF test.sched | ||
141 | |||
142 | A longer form can be used for proc entries not in /proc/litmus: | ||
143 | |||
144 | $ echo "/proc/sys/something{hello}" | ||
145 | 10 20" > test.sched | ||
146 | |||
147 | You can specify your own spin programs to run as well instead of | ||
148 | rtspin by putting their name at the beginning of the line. | ||
149 | |||
150 | $ echo "colorspin -f color1.csv 10 20" > test.sched | ||
151 | |||
152 | This example also shows how you can reference files in the same | ||
153 | directory as the schedule file on the command line. | ||
154 | |||
155 | You can specify parameters for an experiment in a file instead of on | ||
156 | the command line using params.py (the -p option lets you choose the | ||
157 | name of this file if params.py is not for you): | ||
158 | |||
159 | $ echo "{'scheduler':'GSN-EDF', 'duration':10}" > params.py | ||
160 | $ run_exps.py test.sched | ||
161 | |||
162 | You can also run multiple experiments with a single command, provided | ||
163 | a directory with a schedule file exists for each. By default, the | ||
164 | program will look for sched.py for the schedule file and params.py for | ||
165 | the parameter file, but this behavior can be changed using the -p and | ||
166 | -c options. | ||
167 | |||
168 | You can include non-relevant parameters which run_exps.py does not | ||
169 | understand in params.py. These parameters will be saved with the data | ||
170 | output by run_exps.py. This is useful for tracking variations in | ||
171 | system parameters versus experimental results. | ||
172 | |||
173 | In the following example, multiple experiments are demonstrated and an | ||
174 | extra parameter 'test-param' is included: | ||
175 | |||
176 | $ mkdir test1 | ||
177 | # The duration will default to 30 and need not be specified | ||
178 | $ echo "{'scheduler':'C-EDF', 'test-param':1} > test1/params.py | ||
179 | $ echo "10 20" > test1/sched.py | ||
180 | $ cp -r test1 test2 | ||
181 | $ echo "{'scheduler':'GSN-EDF', 'test-param':2}"> test2/params.py | ||
182 | $ run_exps.py test* | ||
183 | |||
184 | Finally, you can specify system properties in params.py which the | ||
185 | environment must match for the experiment to run. These are useful if | ||
186 | you have a large batch of experiments which must be run under | ||
187 | different kernels. The first property is a regular expression for the | ||
188 | uname of the system: | ||
189 | |||
190 | $ uname -r | ||
191 | 3.0.0-litmus | ||
192 | $ cp params.py old_params.py | ||
193 | $ echo "{'uname': r'.*linux.*'}" >> params.py | ||
194 | # run_exps.py will now complain of an invalid environment for this | ||
195 | experiment | ||
196 | $ cp old_params.py params.py | ||
197 | $ echo "{'uname': r'.*litmus.*'}" >> params.py | ||
198 | # run_exps.py will now succeed | ||
199 | |||
200 | The second property are kernel configuration options. These assume the | ||
201 | configuration is stored at /boot/config-`uname -r`. You can specify | ||
202 | these like so: | ||
203 | |||
204 | $ echo "{'config-options':{ | ||
205 | 'RELEASE_MASTER' : 'y', | ||
206 | 'ARM' : 'y'}}" >> params.py | ||
207 | # Only executes on ARM systems with the release master enabled | ||
208 | |||
209 | |||
210 | III. GEN_EXPS | ||
211 | Usage: gen_exps.py [options] [files...] [generators...] [param=val[,val]...] | ||
212 | Output: exps/EXP_DIRS which each contain sched.py and params.py | ||
213 | Defaults: generators = G-EDF P-EDF C-EDF | ||
214 | |||
215 | The gen_exps.py script uses 'generators', one for each LITMUS | ||
216 | scheduler supported, which each have different properties which can be | ||
217 | varied to generate different types of schedules. Each of these | ||
218 | properties has a default value which can be modified on the command | ||
219 | line for quick and easy experiment generation. | ||
220 | |||
221 | This script as written should be used to create debugging task sets, | ||
222 | but not for creating task sets for experiments shown in papers. That | ||
223 | is because the safety features of run_exps.py described above (uname, | ||
224 | config-options) are not used here. If you are creating experiments for | ||
225 | a paper, you should create your own generator which outputs values for | ||
226 | 'config-options' required for your plugin so that you cannot ruin your | ||
227 | experiments at run time. | ||
228 | |||
229 | The -l option lists the supported generators which can be specified: | ||
230 | |||
231 | $ gen_exps.py -l | ||
232 | G-EDF, P-EDF, C-EDF | ||
233 | |||
234 | The -d option will describe the properties of a generator or | ||
235 | generators and their default values. Note that some of these defaults | ||
236 | will vary depending on the system the script is run. For example, | ||
237 | 'cpus' defaults to the number of cpus on the current system, in this | ||
238 | example 24. | ||
239 | |||
240 | $ gen_exps.py -d G-EDF,P-EDF | ||
241 | Generator GSN-EDF: | ||
242 | num_tasks -- Number of tasks per experiment. | ||
243 | Default: [24, 48, 72, 96] | ||
244 | Allowed: <type 'int'> | ||
245 | .... | ||
246 | |||
247 | Generator PSN-EDF: | ||
248 | num_tasks -- Number of tasks per experiment. | ||
249 | Default: [24, 48, 72, 96] | ||
250 | Allowed: <type 'int'> | ||
251 | cpus -- Number of processors on target system. | ||
252 | Default: [24] | ||
253 | Allowed: <type 'int'> | ||
254 | .... | ||
255 | |||
256 | You create experiments by specifying a generator. The following will | ||
257 | create experiments 4 schedules with 24, 48, 72, and 96 tasks, because | ||
258 | the default value of num_tasks is an array of these values | ||
259 | |||
260 | $ gen_exps.py P-EDF | ||
261 | $ ls exps/ | ||
262 | sched=GSN-EDF_num-tasks=24/ sched=GSN-EDF_num-tasks=48/ | ||
263 | sched=GSN-EDF_num-tasks=72/ sched=GSN-EDF_num-tasks=96/ | ||
264 | |||
265 | You can modify the default using a single value (the -f option deletes | ||
266 | previous experiments in the output directory, defaulting to 'exps/', | ||
267 | changeable with -o): | ||
268 | |||
269 | $ gen_exps.py -f P-EDF num_tasks=24 | ||
270 | $ ls exps/ | ||
271 | sched=GSN-EDF_num-tasks=24/ | ||
272 | |||
273 | Or with an array of values, specified as a comma-seperated list: | ||
274 | |||
275 | $ gen_exps.py -f num_tasks=`seq -s, 24 2 30` P-EDF | ||
276 | sched=PSN-EDF_num-tasks=24/ sched=PSN-EDF_num-tasks=26/ | ||
277 | sched=PSN-EDF_num-tasks=28/ sched=PSN-EDF_num-tasks=30/ | ||
278 | |||
279 | The generator will create a different directory for each possible | ||
280 | configuration of the parameters. Each parameter which is varied is | ||
281 | included in the name of the schedule directory. For example, to vary | ||
282 | the number of CPUs but not the number of tasks: | ||
283 | |||
284 | $ gen_exps.py -f num_tasks=24 cpus=3,6 P-EDF | ||
285 | $ ls exps | ||
286 | sched=PSN-EDF_cpus=3/ sched=PSN-EDF_cpus=6/ | ||
287 | |||
288 | The values of non-varying parameters are still saved in | ||
289 | params.py. Continuing the example above: | ||
290 | |||
291 | $ cat exps/sched\=PSN-EDF_cpus\=3/params.py | ||
292 | {'periods': 'harmonic', 'release_master': False, 'duration': 30, | ||
293 | 'utils': 'uni-medium', 'scheduler': 'PSN-EDF', 'cpus': 3} | ||
294 | |||
295 | You can also have multiple schedules generated with the same | ||
296 | configuration using the -n option: | ||
297 | |||
298 | $ gen_exps.py -f num_tasks=24 -n 5 P-EDF | ||
299 | $ ls exps/ | ||
300 | sched=PSN-EDF_trial=0/ sched=PSN-EDF_trial=1/ sched=PSN-EDF_trial=2/ | ||
301 | sched=PSN-EDF_trial=3/ sched=PSN-EDF_trial=4/ | ||
302 | |||
303 | |||
304 | IV. PARSE_EXPS | ||
305 | Usage: parse_exps.py [options] [data_dir1] [data_dir2]... | ||
306 | where data_dirs contain feather-trace and sched-trace data, | ||
307 | e.g. ft.bin, mysched.ft, or st-*.bin. | ||
308 | |||
309 | Output: print out all parsed data or | ||
310 | OUT_FILE where OUT_FILE is a python map of the data or | ||
311 | OUT_DIR/[FIELD]*/[PARAM]/[TYPE]/[TYPE]/[LINE].csv | ||
312 | |||
313 | The goal is to create csv files which record how varying PARAM | ||
314 | changes the value of FIELD. Only PARAMs which vary are | ||
315 | considered. | ||
316 | |||
317 | FIELD is a parsed value, e.g. 'RELEASE' overhead or 'miss-ratio' | ||
318 | PARAM is a parameter which we are going to vary, e.g. 'tasks' | ||
319 | A single LINE is created for every configuration of parameters | ||
320 | other than PARAM. | ||
321 | |||
322 | TYPE is the type of measurement, i.e. Max, Min, Avg, or | ||
323 | Var[iance]. The two types are used to differentiate between | ||
324 | measurements across tasks in a single taskset, and | ||
325 | measurements across all tasksets. E.g. miss-ratio/*/Max/Avg | ||
326 | is the maximum of all the average miss ratios for each task set, while | ||
327 | miss-ratio/*/Avg/Max is the average of the maximum miss ratios | ||
328 | for each task set. | ||
329 | |||
330 | Defaults: OUT_DIR or OUT_FILE = parse-data, data_dir1 = '.' | ||
331 | |||
332 | The parse_exps.py script reads a directory or directories, parses the | ||
333 | binary files inside for feather-trace or sched-trace data, then | ||
334 | summarizes and organizes the results for output. The output can be to | ||
335 | the console, to a python map, or to a directory tree of csvs (the | ||
336 | default, ish). The python map (using -m) can be used for | ||
337 | schedulability tests. The directory tree can be used to look at how | ||
338 | changing parameters affects certain measurements. | ||
339 | |||
340 | The script will use half the current computers CPUs to process data. | ||
341 | |||
342 | In the following example, too little data was found to create csv | ||
343 | files, so the data is output to the console despite the user not | ||
344 | specifying the -v option. This use is the easiest for quick overhead | ||
345 | evalutation and debugging. Note that for overhead measurements like | ||
346 | these, parse_exps.py will use the 'clock-frequency' parameter saved in | ||
347 | a params.py file by run_exps.py to calculate overhead measurements. If | ||
348 | a param file is not present, as in this case, the current CPUs | ||
349 | frequency will be used. | ||
350 | |||
351 | $ ls run-data/ | ||
352 | taskset_scheduler=C-FL-split-L3_host=ludwig_n=10_idx=05_split=randsplit.ft | ||
353 | $ parse_exps.py run-data/ | ||
354 | Loading experiments... | ||
355 | Parsing data... | ||
356 | 0.00% | ||
357 | Writing result... | ||
358 | Too little data to make csv files. | ||
359 | <ExpPoint-/home/hermanjl/tmp/run-data> | ||
360 | CXS: Avg: 5.053 Max: 59.925 Min: 0.241 | ||
361 | SCHED: Avg: 4.410 Max: 39.350 Min: 0.357 | ||
362 | TICK: Avg: 1.812 Max: 21.380 Min: 0.241 | ||
363 | |||
364 | In the next example, because the value of num-tasks varies, csvs can | ||
365 | be created: | ||
366 | |||
367 | $ ls run-data/ | ||
368 | sched=C-EDF_num-tasks=4/ sched=GSN-EDF_num-tasks=4/ | ||
369 | sched=C-EDF_num-tasks=8/ sched=GSN-EDF_num-tasks=8/ | ||
370 | sched=C-EDF_num-tasks=12/ sched=GSN-EDF_num-tasks=12/ | ||
371 | sched=C-EDF_num-tasks=16/ sched=GSN-EDF_num-tasks=16/ | ||
372 | $ parse_exps.py run-data/* | ||
373 | $ ls parse-data/ | ||
374 | avg-block/ avg-tard/ max-block/ max-tard/ miss-ratio/ | ||
375 | |||
376 | The varying parameters were found by reading the params.py files under | ||
377 | each run-data subdirectory. | ||
378 | |||
379 | You can use the -v option to print out the values measured even when | ||
380 | csvs could be created. | ||
381 | |||
382 | You can use the -i option to ignore variations in a certain parameter | ||
383 | (or parameters if a comma-seperated list is given). In the following | ||
384 | example, the user has decided the 'option' does not matter after | ||
385 | viewing output. Note that the 'trial' parameter, used by gen_exps.py | ||
386 | to create multiple schedules with the same configuration, is always | ||
387 | ignored. | ||
388 | |||
389 | $ ls run-data/ | ||
390 | sched=C-EDF_num-tasks=4_option=1/ sched=C-EDF_num-tasks=4_option=2/ | ||
391 | sched=C-EDF_num-tasks=8_option=1/ sched=C-EDF_num-tasks=8_option=2/ | ||
392 | $ parse_exps.py run-data/* | ||
393 | $ for i in `ls parse-data/miss-ratio/tasks/Avg/Avg/`; do echo $i; cat | ||
394 | $i; done | ||
395 | option=1.csv | ||
396 | 4 .1 | ||
397 | 8 .2 | ||
398 | option=2.csv | ||
399 | 4 .2 | ||
400 | 8 .4 | ||
401 | # Now ignore 'option' for more accurate results | ||
402 | $ parse_exps.py -i option run-data/* | ||
403 | $ for i in `ls parse-data/miss-ratio/tasks/Avg/Avg/`; do echo $i; cat | ||
404 | $i; done | ||
405 | line.csv | ||
406 | 4 .2 | ||
407 | 8 .3 | ||
408 | |||
409 | The second command will also have run faster than the first. This is | ||
410 | because parse_exps.py will save the data it parses in tmp/ directories | ||
411 | before it attempts to sort it into csvs. Parsing takes far longer than | ||
412 | sorting, so this saves a lot of time. The -f flag can be used to | ||
413 | re-parse files and overwrite this saved data. | ||
414 | |||
415 | All output from the feather-trace-tool programs used to parse data is | ||
416 | stored in the tmp/ directories created in the input directories. If | ||
417 | the sched_trace repo is found in the users PATH, st_show will be used | ||
418 | to create a human-readable version of the sched-trace data which will | ||
419 | also be stored there. | ||
420 | |||
421 | |||
422 | V. PLOT_EXPS | ||
423 | Usage: plot_exps.py [options] [csv_dir]... | ||
424 | where a csv dir is a directory or directory of directories (and | ||
425 | so on) containing csvs, like: | ||
426 | csv_dir/[subdirs/...] | ||
427 | line1.csv | ||
428 | line2.csv | ||
429 | line3.csv | ||
430 | |||
431 | Outputs: OUT_DIR/[csv_dir/]*[plot]*.pdf | ||
432 | where a single plot exists for each directory of csvs, with a | ||
433 | line for for each csv file in that directory. If only a | ||
434 | single csv_dir is specified, all plots are placed directly | ||
435 | under OUT_DIR. | ||
436 | |||
437 | Defaults: OUT_DIR = 'plot-data/', csv_dir = '.' | ||
438 | |||
439 | The plot_exps.py script takes directories of csvs (or directories | ||
440 | formatted as specified below) and creates a pdf plot of each csv | ||
441 | directory found. A line is created for each .csv file contained in a | ||
442 | plot. Matplotlib is used to do the plotting. | ||
443 | |||
444 | If the csv files are formatted like: | ||
445 | |||
446 | param=value_param2=value2.csv | ||
447 | |||
448 | the variation of these parameters will be used to color the lines in | ||
449 | the most readable way. For instance, if there are three parameters, | ||
450 | variations in one parameter will change line color, another line | ||
451 | style (dashes/dots/etc), and a third line markers | ||
452 | (trianges/circles/etc). | ||
453 | |||
454 | If a directory of directories is passed in, the script will assume the | ||
455 | top level directory is the measured value and the next level is the | ||
456 | variable, ie: | ||
457 | |||
458 | value/variable/[..../]line.csv | ||
459 | |||
460 | And put a title on the plot of "Value by variable (...)". Otherwise, | ||
461 | the name of the top level directory will be the title, like "Value". | ||
462 | |||
463 | A directory with some lines: | ||
464 | $ ls | ||
465 | line1.csv line2.csv | ||
466 | $ plot_exps.py | ||
467 | $ ls plot-data/ | ||
468 | plot.pdf | ||
469 | |||
470 | A directory with a few subdirectories: | ||
471 | $ ls test/ | ||
472 | apples/ oranges/ | ||
473 | $ ls test/apples/ | ||
474 | line1.csv line2.csv | ||
475 | $ plot_exps.py test/ | ||
476 | $ ls plot-data/ | ||
477 | apples.pdf oranges.pdf | ||
478 | |||
479 | A directory with many subdirectories: | ||
480 | $ ls parse-data | ||
481 | avg-block/ avg-tard/ max-block/ max-tard/ miss-ratio/ | ||
482 | $ ls parse-data/avg-block/tasks/Avg/Avg | ||
483 | scheduler=C-EDF.csv scheduler=PSN-EDF.csv | ||
484 | $ plot_exps.py parse-data | ||
485 | $ ls plot-data | ||
486 | avg-block_tasks_Avg_Avg.pdf avg-block_tasks_Avg_Max.pdf avg-block_tasks_Avg_Min.pdf | ||
487 | avg-block_tasks_Max_Avg.pdf avg-block_tasks_Max_Max.pdf avg-block_tasks_Max_Min.pdf | ||
488 | avg-block_tasks_Min_Avg.pdf avg-block_tasks_Min_Max.pdf avg-block_tasks_Min_Min.pdf | ||
489 | avg-block_tasks_Var_Avg.pdf avg-block_tasks_Var_Max.pdf avg-block_tasks_Var_Min.pdf | ||
490 | ....... | ||
491 | |||
492 | If you run the previous example directly on the subdirectories, | ||
493 | subdirectories will be created in the output: | ||
494 | |||
495 | $ plot_exps.py parse-data/* | ||
496 | $ ls plot-data/ | ||
497 | avg-block/ max-tard/ avg-tard/ miss-ratio/ max-block/ | ||
498 | $ ls plot-data/avg-block/ | ||
499 | tasks_Avg_Avg.pdf tasks_Avg_Min.pdf tasks_Max_Max.pdf | ||
500 | tasks_Min_Avg.pdf tasks_Min_Min.pdf tasks_Var_Max.pdf | ||
501 | tasks_Avg_Max.pdf tasks_Max_Avg.pdf tasks_Max_Min.pdf | ||
502 | tasks_Min_Max.pdf tasks_Var_Avg.pdf tasks_Var_Min.pdf | ||
503 | |||
504 | However, when a single directory of directories is given, the script | ||
505 | assumes the experiments are related and can make line styles match in | ||
506 | different plots and more effectively parallelize the plotting. | ||
507 | |||