11#!/usr/bin/env python3
2+ """
3+ Run SOFA benchmarks from a JSON config file.
4+
5+ Usage:
6+ python runBenchmarks_script.py -config benchmarks.json
7+ python runBenchmarks_script.py -config benchmarks.json -output results/my_run
8+
9+ Change the SOFA executable:
10+ python runBenchmarks_script.py -config benchmarks.json -sofa_exe /path/to/runSofa
11+
12+ Load SofaPython3:
13+ python runBenchmarks_script.py -config benchmarks.json -python
14+
15+ Override Parameters:
16+ python runBenchmarks_script.py -config benchmarks.json -n_tests 5 -warmup 2 -iterations 1000 -timeout 60
17+
18+ Required config keys: iterations, n_tests, timeout, cases
19+ Optional config keys: sofa_exe (default: runSofa), warmup (default: 1), output (default: log.benchmark)
20+ CLI flags override the corresponding config-file values.
21+ """
222import os
323import re
424import sys
@@ -54,6 +74,7 @@ def stats(self) -> Optional[Dict[str, float]]:
5474
5575DEFAULTS : Dict [str , Any ] = {
5676 'sofa_exe' : 'runSofa' ,
77+ 'python' : False ,
5778 'warmup' : 1 ,
5879 'output' : 'log.benchmark' ,
5980}
@@ -62,6 +83,7 @@ def stats(self) -> Optional[Dict[str, float]]:
6283REQUIRED_KEYS = ('iterations' , 'n_tests' , 'timeout' )
6384
6485# All keys overrideable via CLI — must match build_parser arguments exactly.
86+ # 'python' uses store_true with default=None so it only overrides when explicitly passed.
6587OVERRIDE_KEYS = (* DEFAULTS .keys (), * REQUIRED_KEYS )
6688
6789
@@ -132,12 +154,13 @@ def _parse_timing_line(line: str) -> Optional[RunResult]:
132154
133155
134156def run_single (
135- sofa_exe : str , scene : str , iterations : int , timeout : int
157+ sofa_exe : str , scene : str , iterations : int , timeout : int , python : bool = False
136158) -> Tuple [Optional [RunResult ], Optional [str ]]:
137159 """Returns (RunResult, None) on success, (None, error_message) on failure. Never raises."""
160+ python_args = ['-l' , 'SofaPython3' ] if python else []
138161 try :
139162 proc = subprocess .run (
140- [sofa_exe , '-g' , 'batch' , '-n' , str (iterations ), scene ],
163+ [sofa_exe , * python_args , '-g' , 'batch' , '-n' , str (iterations ), scene ],
141164 capture_output = True ,
142165 text = True ,
143166 timeout = timeout ,
@@ -170,14 +193,15 @@ def run_case(config: Dict[str, Any], case: Dict[str, str]) -> CaseResults:
170193 scene = case ['scene' ]
171194 name = case ['name' ]
172195
196+ python = config .get ('python' , False )
173197 cr = CaseResults (name = name , scene = scene )
174198
175199 for i in range (warmup + n_tests ):
176200 is_warmup = i < warmup
177201 label = f'warmup { i + 1 } /{ warmup } ' if is_warmup else f'test { i - warmup + 1 } /{ n_tests } '
178202 print (f' [{ name } ] { label } ... ' , end = '' , flush = True )
179203
180- result , error = run_single (sofa_exe , scene , iterations , timeout )
204+ result , error = run_single (sofa_exe , scene , iterations , timeout , python )
181205
182206 if result is not None :
183207 suffix = ' [warmup, discarded]' if is_warmup else ''
@@ -250,6 +274,7 @@ def build_parser() -> argparse.ArgumentParser:
250274 )
251275 p .add_argument ('-config' , required = True , help = 'Path to JSON config file' )
252276 p .add_argument ('-sofa_exe' , default = None , help = 'Override: path to runSofa executable' )
277+ p .add_argument ('-python' , action = 'store_true' , default = None , help = 'Override: load SofaPython3 (-l SofaPython3)' )
253278 p .add_argument ('-iterations' , default = None , type = int , help = 'Override: ODE iterations per run' )
254279 p .add_argument ('-n_tests' , default = None , type = int , help = 'Override: timed test runs per case' )
255280 p .add_argument ('-warmup' , default = None , type = int , help = 'Override: warmup runs (discarded from stats)' )
0 commit comments