source: soft/giet_vm/applications/rosenfeld/scripts/run_simus.py @ 822

Last change on this file since 822 was 822, checked in by meunier, 8 years ago

In rosenfeld:

  • Updated nrio0, nrio1, nrio2, nrio1f, nrio2f, nrio1x, nrbool1, nrbool2 and nralloc1 in the nrc2 lib in order to use macro-typed functions
  • Updated the simulation script to include performance evaluation with random images, and a script to generate graphs
  • Updated the clock.h to use 64-bit integers, which potentially breaks the printing on the giet
  • Property svn:executable set to *
File size: 11.7 KB
Line 
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4# Note: This code should stay compatible with
5# python 2 as it will execute on computation servers
6
7
8from __future__ import print_function
9import os
10import sys
11import re
12import filecmp
13import shutil
14import random
15
16from common import *
17
18# Directories and files
19top_path = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
20scripts_path  = os.path.join(top_path, "scripts")
21pyconf_file   = os.path.join(scripts_path, "config.py")
22config_file   = os.path.join(top_path, "include/config.h")
23images_dir    = os.path.join(top_path, "../../images")
24binary_file   = os.path.join(top_path, "appli.elf")
25
26base_output_dir   = "output" # For output images and stat files (ref + exec)
27base_logs_dir     = "logs"   # Log of execution, i.e. what is printed on screen
28base_data_dir     = "data"   # For timing information extracted
29base_rand_img_dir = "random_images" # For storing random images if using dsk
30
31
32
33#images = ['boulons.pgm', 'cadastre.pgm', 'alea1.pgm', 'alea2.pgm', 'alea3.pgm']
34images = ['cadastre.pgm']
35
36images = map(lambda x:os.path.join(images_dir, x), images)
37
38# Parameters
39num_runs = 10
40check_results = False
41eval_perf = True
42use_valgrind = False
43use_rand_images = True
44threads = [1, 2, 4]
45use_dsk = True
46# Using dsk will store generated random images, otherwise they are re-generated at each run to save disk space
47
48# Configurations
49configs = [
50        {'SLOW':'1', 'FAST':'0', 'FEATURES':'0', 'PARMERGE':'0', 'ARSP':'0'},
51        {'SLOW':'0', 'FAST':'1', 'FEATURES':'0', 'PARMERGE':'0', 'ARSP':'0'},
52        {'SLOW':'1', 'FAST':'0', 'FEATURES':'1', 'PARMERGE':'0', 'ARSP':'0'},
53        {'SLOW':'0', 'FAST':'1', 'FEATURES':'1', 'PARMERGE':'0', 'ARSP':'0'},
54        #{'SLOW':'0', 'FAST':'1', 'FEATURES':'1', 'PARMERGE':'1', 'ARSP':'0'},
55        #{'SLOW':'0', 'FAST':'1', 'FEATURES':'0', 'PARMERGE':'1', 'ARSP':'1'},
56]
57
58
59# Other parameters which shouldn't be changed
60rand_seed = 7
61granularity = 1 # constant for now
62img_size = 1024
63
64check_pyconf_file(pyconf_file)
65
66# Loading config file
67exec(file(pyconf_file))
68
69if use_dsk:
70    try:
71        dsk_dir
72        if not os.path.exists(dsk_dir):
73            print("mkdir %s", dsk_dir)
74            os.mkdir(dsk_dir)
75    except NameError:
76        print("*** Warning: variable dsk_dir is not defined in %s file; using current directory for storing output files" % (short_path(pyconf_file)))
77        use_dsk = False
78    except OSError:
79        print("*** Warning: Impossible to create directory %s; using current directory for storing output files" % (dsk_dir))
80        use_dsk = False
81
82
83# Updating output directories
84if use_dsk:
85    output_dir   = os.path.join(dsk_dir, base_output_dir)
86    logs_dir     = os.path.join(dsk_dir, base_logs_dir)
87    data_dir     = os.path.join(dsk_dir, base_data_dir)
88    rand_img_dir = os.path.join(dsk_dir, base_rand_img_dir)
89else:
90    output_dir = os.path.join(scripts_path, base_output_dir)
91    logs_dir   = os.path.join(scripts_path, base_logs_dir)
92    data_dir   = os.path.join(scripts_path, base_data_dir)
93
94
95
96def gen_random_image(filename, x, y, granularity, density, seed):
97    random.seed(seed)
98    img = [[0 for a in range(x)] for b in range(y)] 
99    for i in range(0, x, granularity):
100        for j in range(0, y, granularity):
101            r = random.random();
102            if r < density:
103                px = 255
104            else:
105                px = 0
106
107            for di in range(0, granularity):
108                for dj in range(0, granularity):
109                    if i + di < x and j + dj < y:
110                        img[i + di][j + dj] = px;
111
112    f = open(filename, 'wb')
113    f.write("P5\n%d %d\n255\n" % (x, y))
114    for j in range(0, y):
115        bimg = bytearray(img[j])
116        f.write(bimg)
117    f.close()
118
119
120
121def update_config_file(config):
122    if os.path.isfile(config_file):
123        print("# Updating file %s" % (config_file))
124        f = open(config_file, "r")
125        lines = f.readlines()
126        f.close()
127
128        f = open(config_file, "w")
129
130        for line in lines:
131            line_with_key = False
132            for key in config.keys():
133                if "#define %s" % (key) in line:
134                    f.write("#define %s %s\n" % (key, config[key]))
135                    line_with_key = True
136                    break
137            if not line_with_key:
138                f.write(line)
139
140        f.close()
141    else:
142        print("# Creating file %s" % (config_file))
143        f = open(config_file, "w")
144        f.write("\n")
145        for key in config.keys():
146            f.write("#define %s %s\n" % (key, config[key]))
147        f.write("\n")
148        f.close()
149
150
151
152
153if not os.path.exists(output_dir):
154    my_mkdir(output_dir)
155
156if not os.path.exists(logs_dir):
157    my_mkdir(logs_dir)
158
159if not os.path.exists(data_dir):
160    my_mkdir(data_dir)
161
162if use_dsk and not os.path.exists(rand_img_dir):
163    my_mkdir(rand_img_dir)
164
165
166
167
168stat_array = {}
169perf_array = {}
170
171for config in configs:
172    img_idx = 0
173    fconfig = frozenset(config.iteritems())
174    perf_array[fconfig] = {}
175    update_config_file(config)
176    features = config['FEATURES'] == '1'
177   
178    # Compile application
179    my_chdir(top_path)
180    cmd = ['make']
181    print_and_call(cmd)
182    my_chdir(scripts_path)
183
184    while not use_rand_images and img_idx != len(images) or use_rand_images and img_idx != 101:
185        # Compute image and stat filenames
186        if use_rand_images:
187            if use_dsk:
188                random_img_file = get_random_img_file(img_idx, img_size, img_size, granularity, rand_seed)
189                random_img_file = os.path.join(rand_img_dir, random_img_file)
190            else:
191                random_img_file = "random.pgm"
192            if not (use_dsk and os.path.isfile(random_img_file)):
193                # We re-generate the random image if not using the dsk or if it does not exist
194                print("# Generating random image %s with density = %d" % (random_img_file, img_idx))
195                gen_random_image(random_img_file, img_size, img_size, 1, float(img_idx) / 100, rand_seed)
196
197            image = random_img_file
198        else:
199            image = images[img_idx]
200        img_basename = os.path.splitext(os.path.basename(image))[0]
201        perf_array[fconfig][img_basename] = {}
202        ref_bmpfile  = os.path.join(output_dir, os.path.splitext(os.path.basename(image))[0] + "_ref.bmp")
203        ref_statfile = os.path.join(output_dir, os.path.splitext(os.path.basename(image))[0] + "_ref.txt")
204
205        for nthreads in threads:
206            perf_array[fconfig][img_basename][nthreads] = {}
207            for run in range(num_runs):
208                if not os.path.exists(ref_bmpfile):
209                    bmpfile = ref_bmpfile
210                else:
211                    bmpfile = os.path.join(output_dir, os.path.splitext(os.path.basename(image))[0] + ".bmp")
212                    if os.path.exists(bmpfile):
213                        os.remove(bmpfile)
214   
215                if not os.path.exists(ref_statfile):
216                    statfile = ref_statfile
217                else:
218                    statfile = os.path.join(output_dir, os.path.splitext(os.path.basename(image))[0] + ".txt")
219   
220                cmd = []
221                if use_valgrind:
222                    cmd.append('valgrind')
223   
224                cmd.extend([short_path(binary_file), '-n', str(nthreads), '-i', short_path(image)])
225               
226                if check_results:
227                    cmd.extend(['-o', short_path(bmpfile), '-g'])
228               
229                if check_results and features:
230                    cmd.append('-d')
231   
232                config_keys = config.keys()
233                logfile = get_filename(logs_dir, nthreads, config, features, img_basename)
234                output = print_and_popen(cmd, logfile)
235                outlines = output.splitlines()
236
237                # if performance evaluation, get timing measurements
238                if eval_perf:
239                    for line in outlines:
240                        tokens = line.split()
241                        if len(tokens) == 0:
242                            continue
243                        tag = tokens[0]
244                        pattern = re.compile('\[THREAD_STEP_([0-9]+)\]');
245                        match = pattern.match(tag)
246                        if match:
247                            step = match.group(1)
248                            value = tokens[len(tokens) - 1]
249                            if step in perf_array[fconfig][img_basename][nthreads]:
250                                # Accumulating times over the num_runs runs
251                                perf_array[fconfig][img_basename][nthreads][step] += int(value)
252                            else:
253                                perf_array[fconfig][img_basename][nthreads][step] = int(value)
254
255
256                # Checking against reference output image   
257                if check_results and bmpfile != ref_bmpfile:
258                    print("diff %s %s" % (short_path(bmpfile), short_path(ref_bmpfile)))
259                    if not filecmp.cmp(bmpfile, ref_bmpfile):
260                        print("*** Error: files %s and %s differ" % (short_path(bmpfile), short_path(ref_bmpfile)))
261                        sys.exit(1)
262   
263                # Checking for valgrind errors
264                if use_valgrind:
265                    if not "== ERROR SUMMARY: 0 errors from 0 contexts" in output:
266                        print("*** Error: Valgrind error")
267                        sys.exit(1)
268                    if not "== All heap blocks were freed -- no leaks are possible" in output:
269                        print("*** Error: Valgrind detected a memory leak")
270                        sys.exit(1)
271   
272                # Extracting features for correctness verification
273                if check_results and features:
274                    stat_array = {}
275                    in_stats = False
276                    index = 0
277                    for line in outlines:
278                        if "[STATS]" in line:
279                            in_stats = True
280                            continue
281                        if "[/STATS]" in line:
282                            in_stats = False
283                            break
284                        if in_stats:
285                            tokens = line.split()
286                            assert(len(tokens) == 8)
287                            stat_array[index] = {}
288                            for j in range(len(tokens)):
289                                stat_array[index][j] = tokens[j]
290                            index += 1
291   
292                    # Dump stat array in stat file
293                    file = open(statfile, 'w')
294                    for i in range(len(stat_array)):
295                        for j in range(8):
296                            file.write("%s " % stat_array[i][j])
297                        file.write("\n");
298                    file.close()
299   
300                    # Comparison to reference
301                    if statfile != ref_statfile:
302                        print("diff %s %s" % (short_path(statfile), short_path(ref_statfile)))
303                        if not filecmp.cmp(statfile, ref_statfile):
304                            print("*** Error: feature files %s and %s differ" % (short_path(statfile), short_path(ref_statfile)))
305                            sys.exit(1)
306
307            # End of the num_runs simus
308            if eval_perf:
309                if use_rand_images:
310                    idx = img_idx
311                else:
312                    idx = None
313                datafile = get_filename(data_dir, nthreads, config, features, img_basename)
314                file = open(datafile, 'w')
315                for step in sorted(perf_array[fconfig][img_basename][nthreads].keys()):
316                    # Average time for each step
317                    file.write("[STEP_%s]   %d\n" % (step, perf_array[fconfig][img_basename][nthreads][step] / num_runs))
318
319        img_idx += 1
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
Note: See TracBrowser for help on using the repository browser.