devstone_comparative.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import argparse
  2. import csv
  3. import re
  4. import subprocess
  5. import sys
  6. import time
  7. import os
  8. sys.setrecursionlimit(10000)
  9. threads = os.cpu_count()
  10. XDEVS_PYTHON_CMD = "python3 simulators/xdevs-python/perfdevs/examples/devstone/main.py -m {model_type} -d {depth} -w {width} -i {int_cycles} -e {ext_cycles}"
  11. XDEVS_PYTHON_F_CMD = "python3 simulators/xdevs-python/perfdevs/examples/devstone/main.py -m {model_type} -d {depth} -w {width} -i {int_cycles} -e {ext_cycles} -f"
  12. XDEVS_PYTHON_C_CMD = "python3 simulators/xdevs-python/perfdevs/examples/devstone/main.py -m {model_type} -d {depth} -w {width} -i {int_cycles} -e {ext_cycles} -c"
  13. XDEVS_PYTHON_FC_CMD = "python3 simulators/xdevs-python/perfdevs/examples/devstone/main.py -m {model_type} -d {depth} -w {width} -i {int_cycles} -e {ext_cycles} -f -c"
  14. XDEVS_JAVA_CMD = "java -classpath simulators/xdevs-java/out/ xdevs.core.devstone.DEVStone {model_type} {depth} {width} {int_cycles} {ext_cycles} coord false"
  15. XDEVS_JAVA_CHAINED_CMD = "java -classpath simulators/xdevs-java/out/ xdevs.core.devstone.DEVStone {model_type} {depth} {width} {int_cycles} {ext_cycles} chained false"
  16. XDEVS_JAVA_PARALLEL_CMD = "java -classpath simulators/xdevs-java/out/ xdevs.core.devstone.DEVStone {model_type} {depth} {width} {int_cycles} {ext_cycles} parallel false"
  17. XDEVS_JAVA_PARALLEL_CHAINED_CMD = "java -classpath simulators/xdevs-java/out/ xdevs.core.devstone.DEVStone {model_type} {depth} {width} {int_cycles} {ext_cycles} chainedparallel false"
  18. PYPDEVS_CMD = "python3 devstone/pythonpdevs/main.py -m {model_type} -d {depth} -w {width} -i {int_cycles} -e {ext_cycles}"
  19. PYPDEVS_MIN_CMD = ""
  20. CADMIUM_CMD = "devstone/cadmium/build/cadmium-dynamic-devstone --kind={model_type} --depth={depth} --width={width} --int-cycles={int_cycles} --ext-cycles={ext_cycles}"
  21. CADMIUM_CONC_CMD = "devstone/cadmium/build/cadmium-dynamic-conc-devstone --kind={model_type} --depth={depth} --width={width} --int-cycles={int_cycles} --ext-cycles={ext_cycles} --threads=" + str(threads)
  22. CDBOOST_CMD = "devstone/cdboost/build/cdboost-devstone --kind={model_type} --depth={depth} --width={width} --int-cycles={int_cycles} --ext-cycles={ext_cycles} --event-list=events_devstone.txt"
  23. ADEVS_CMD = "devstone/adevs/build/DEVStone --kind={model_type} --depth={depth} --width={width} --int-cycles={int_cycles} --ext-cycles={ext_cycles}"
  24. DEFAULT_PARAMS = ((300, 10, 0, 0), (10, 300, 0, 0), (300, 300, 0, 0))
  25. DEFAULT_MODEL_TYPES = ("LI", "HI", "HO", "HOmod")
  26. DEFAULT_MAX_TIME = 1e10
  27. DEFAULT_NUM_REPS = 10
  28. RE_SIM_TIMES = r"Model creation time: ?([0-9.e-]+) ?.*Engine set ?up time: ?([0-9.e-]+) ?.*Simulation time: ?([0-9.e-]+)"
  29. engines = {"xdevs-python": XDEVS_PYTHON_CMD,
  30. "xdevs-python-f": XDEVS_PYTHON_F_CMD,
  31. "xdevs-python-c": XDEVS_PYTHON_C_CMD,
  32. "xdevs-python-fc": XDEVS_PYTHON_FC_CMD,
  33. "xdevs-java": XDEVS_JAVA_CMD,
  34. "xdevs-java-chained": XDEVS_JAVA_CHAINED_CMD,
  35. "xdevs-java-parallel": XDEVS_JAVA_PARALLEL_CMD,
  36. "xdevs-java-parallel-chained": XDEVS_JAVA_PARALLEL_CHAINED_CMD,
  37. "pypdevs": PYPDEVS_CMD,
  38. "pypdevs-min": PYPDEVS_MIN_CMD,
  39. "cadmium": CADMIUM_CMD,
  40. "cadmium-conc": CADMIUM_CONC_CMD,
  41. "cdboost": CDBOOST_CMD,
  42. "adevs": ADEVS_CMD
  43. }
  44. def parse_args():
  45. parser = argparse.ArgumentParser(description='Script to compare DEVStone implementations with different engines')
  46. parser.add_argument('-m', '--model-types', help='DEVStone model type (LI, HI, HO, HOmod)')
  47. parser.add_argument('-d', '--depth', type=int, help='Number of recursive levels of the model.')
  48. parser.add_argument('-w', '--width', type=int, help='Width of each coupled model.')
  49. parser.add_argument('-i', '--int-cycles', type=int, help='Dhrystone cycles executed in internal transitions')
  50. parser.add_argument('-e', '--ext-cycles', type=int, help='Dhrystone cycles executed in external transitions')
  51. parser.add_argument('-n', '--num-rep', type=int, help='Number of repetitions per each engine and configuration')
  52. parser.add_argument('-a', '--include_engines', help='Add specific engines to perform the comparative')
  53. parser.add_argument('-r', '--exclude_engines', help='Exclude specific engines from the comparative')
  54. parser.add_argument('-o', '--out-file', help='Output file path')
  55. parser.add_argument('-p', '--params', help='Specify params in a condensed form: d1-w1-ic1-ec1, d2-w2-ic2-ec2...')
  56. args = parser.parse_args()
  57. if args.model_types:
  58. args.model_types = [x.strip() for x in args.model_types.split(",")]
  59. else:
  60. args.model_types = DEFAULT_MODEL_TYPES
  61. if args.params:
  62. args.params = [x.strip().split("-") for x in args.params.split(",")]
  63. elif args.depth and args.width:
  64. int_cycles = args.int_cycles or 0
  65. ext_cycles = args.ext_cycles or 0
  66. args.params = ((args.depth, args.width, int_cycles, ext_cycles),)
  67. else:
  68. args.params = DEFAULT_PARAMS
  69. if args.include_engines:
  70. args.include_engines = args.include_engines.split(",")
  71. for engine in args.include_engines:
  72. if engine not in engines:
  73. raise RuntimeError("%s is not in the engines list" % engine)
  74. else:
  75. args.include_engines = engines.keys()
  76. if args.exclude_engines:
  77. excluded = args.exclude_engines.split(",")
  78. args.include_engines = [x for x in args.include_engines if x not in excluded]
  79. if not args.num_rep:
  80. args.num_rep = DEFAULT_NUM_REPS
  81. if not args.out_file:
  82. args.out_file = "devstone_%de_%dp_%d.csv" % (len(engines), len(args.params), int(time.time()))
  83. return args
  84. args = parse_args()
  85. if not engines:
  86. raise RuntimeError("No engines were selected.")
  87. def execute_cmd(cmd, csv_writer):
  88. # Execute simulation
  89. try:
  90. result = subprocess.run(engine_cmd_f.split(), stdout=subprocess.PIPE)
  91. except Exception as e:
  92. print("%s: Error executing simulation." % engine)
  93. return
  94. # Read data from output
  95. found = re.search(RE_SIM_TIMES, str(result.stdout))
  96. if not found:
  97. print("%s: Simulation execution times could not be extracted." % engine)
  98. print(result.stdout)
  99. return
  100. model_time, engine_time, sim_time = tuple(map(float, found.groups()))
  101. total_time = sum((model_time, engine_time, sim_time))
  102. # Write results into output file
  103. row = (
  104. engine, i_exec, model_type, depth, width, int_cycles, ext_cycles, model_time, engine_time, sim_time, total_time)
  105. csv_writer.writerow(row)
  106. with open(args.out_file, "w") as csv_file:
  107. csv_writer = csv.writer(csv_file, delimiter=';')
  108. csv_writer.writerow(("engine", "iter", "model", "depth", "width", "int_delay", "ext_delay", "model_time", "runner_time", "sim_time", "total_time"))
  109. for engine in args.include_engines:
  110. engine_cmd = engines[engine]
  111. if len(args.params[0]) == 4:
  112. for model_type in args.model_types:
  113. for depth, width, int_cycles, ext_cycles in args.params:
  114. engine_cmd_f = engine_cmd.format(model_type=model_type, depth=depth, width=width, int_cycles=int_cycles, ext_cycles=ext_cycles)
  115. for i_exec in range(args.num_rep):
  116. if not engine_cmd_f:
  117. continue
  118. print(engine_cmd_f)
  119. execute_cmd(engine_cmd_f, csv_writer)
  120. elif len(args.params[0]) == 5:
  121. for model_type, depth, width, int_cycles, ext_cycles in args.params:
  122. engine_cmd_f = engine_cmd.format(model_type=model_type, depth=depth, width=width, int_cycles=int_cycles,
  123. ext_cycles=ext_cycles)
  124. for i_exec in range(args.num_rep):
  125. if not engine_cmd_f:
  126. continue
  127. print(engine_cmd_f)
  128. execute_cmd(engine_cmd_f, csv_writer)