Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Fix a doc error about actors (Tutorial_algorithms)
[simgrid.git] / tools / sg_xml_energy_ponecore_to_pepsilon.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3
4 # Copyright (c) 2019. The SimGrid Team.
5 # All rights reserved.
6
7 # This program is free software; you can redistribute it and/or modify it
8 # under the terms of the license (GNU LGPL) which comes with this package.
9
10 '''Update 3-part energy consumption syntax in SimGrid XML platform files.
11
12 - watt_per_state: "pIdle:pOneCore:pFull" -> "pIdle:pEpsilon:pFull"
13   This is done by computing pEpsilon from pOneCore, pFull and #core.'''
14 import fnmatch
15 import os
16 import sys
17 import xml.etree.ElementTree as ET
18
19 class TreeBuilderWithComments(ET.TreeBuilder):
20     def comment(self, data):
21         self.start(ET.Comment, {})
22         self.data(data)
23         self.end(ET.Comment)
24
25 def update_platform_file(filename):
26     comment_tb = TreeBuilderWithComments()
27     tree = ET.parse(filename, parser=ET.XMLParser(target=comment_tb))
28     root = tree.getroot()
29
30     parent_dict = {c:p for p in root.iter() for c in p}
31
32     for prop in root.iter('prop'):
33         if 'id' in prop.attrib and prop.attrib['id'] == 'watt_per_state':
34             # Parse energy consumption and core count
35             values_str = "".join(prop.attrib['value'].split()) # remove whitespaces
36             values = values_str.split(',')
37             nb_core = 1
38             if 'core' in parent_dict[prop].attrib:
39                 nb_core = int(parent_dict[prop].attrib['core'])
40             if nb_core < 1: raise Exception(f'Invalid core count: {nb_core}')
41
42             # If a middle value is given, pIdle:pOneCore:pFull is assumed
43             # and converted to pIdle:pEpsilon:pFull
44             consumption_per_pstate = []
45             update_required = False
46             for value in values:
47                 powers = value.split(':')
48                 if len(powers) == 3:
49                     update_required = True
50                     (pIdle, p1, pFull) = [float(x) for x in powers]
51                     if nb_core == 1:
52                         if p1 != pFull:
53                             raise Exception('Invalid energy consumption: ' +
54                                 "A 1-core host has pOneCore != pFull " +
55                                 f'({p1} != {pFull}).\n' +
56                                 'Original watt_per_state value: "{}"'.format(prop.attrib['value']))
57                         pEpsilon = pFull
58                     else:
59                         pEpsilon = p1 - ((pFull - p1) / (nb_core - 1))
60                     consumption_per_pstate.append(f"{pIdle}:{pEpsilon}:{pFull}")
61                     if pIdle > pEpsilon:
62                         print(f"WARNING: pIdle > pEpsilon ({pIdle} > {pEpsilon})")
63                 else: # len(powers) == 2
64                     if nb_core == 1:
65                         update_required = True
66                         (pIdle, pFull) = [float(x) for x in powers]
67                         pEpsilon = pFull
68                         consumption_per_pstate.append(f"{pIdle}:{pEpsilon}:{pFull}")
69                         print(f"WARNING: putting {pFull} as pEpsilon by default for a single core")
70                     else:
71                         consumption_per_pstate.append(value)
72
73             if update_required:
74                 updated_value = ', '.join(consumption_per_pstate)
75                 print(f'"{values_str}" -> "{updated_value}" (core={nb_core})')
76                 prop.attrib['value'] = updated_value
77
78     with open(filename, 'w', encoding='utf-8') as output_file:
79         # xml.etree.ElementTree does not handle doctypes =/
80         # https://stackoverflow.com/questions/15304229/convert-python-elementtree-to-string
81         content = '''<?xml version='1.0' encoding='utf-8'?>
82 <!DOCTYPE platform SYSTEM "https://simgrid.org/simgrid.dtd">
83 {}
84 '''.format(ET.tostring(root, encoding="unicode"))
85         output_file.write(content)
86
87 if __name__ == '__main__':
88     usage = "usage: {cmd} FILE\n\n{doc}".format(cmd=sys.argv[0], doc=__doc__)
89
90     if len(sys.argv) != 2:
91         print(usage)
92         sys.exit(1)
93
94     update_platform_file(sys.argv[1])