Skip to content

Commit dabe73e

Browse files
committed
<refactor>[SBG profiling]: improved causalization profiling
1 parent d54210b commit dabe73e

9 files changed

Lines changed: 158 additions & 85 deletions

File tree

causalize/sbg_implementation/algebraic_loops_detection.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,6 @@ AlgebraicLoopsDetector::AlgebraicLoopsDetector(HorizontalSortingResult& hs_resul
185185

186186
AlgebraicLoopsResult AlgebraicLoopsDetector::detect()
187187
{
188-
189188
SBG::LIB::DirectedSBG loops_dsbg;
190189
{
191190
SBG::Util::Internal::TimeProfiler profiler{"Algebraic loops SBG builder"};

causalize/sbg_implementation/generate_sbg_input.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@
2929
#include "util/ast_visitors/eval_integer.hpp"
3030
#include "util/ast_visitors/matching_exps.hpp"
3131

32-
#include "eval/file_evaluator.hpp"
33-
#include "eval/pretty_print.hpp"
32+
#include <eval/file_evaluator.hpp>
33+
#include <eval/pretty_print.hpp>
34+
#include <util/time_profiler.hpp>
3435

3536
#include <algorithm>
3637
#include <cmath>
@@ -389,6 +390,8 @@ void GenerateSBGInput::setup()
389390

390391
SBGGenerationResult GenerateSBGInput::buildFromModel()
391392
{
393+
SBG::Util::Internal::TimeProfiler profiler{"Horizontal sorting SBG builder"};
394+
392395
// Write SBG program to _sbg_input
393396
setup();
394397
addVariableNodes();

causalize/sbg_implementation/horizontal_sorting.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <algorithms/matching/matching.hpp>
2727
#include <boost/variant/get.hpp>
2828
#include <sbg/bipartite_sbg.hpp>
29+
#include <util/time_profiler.hpp>
2930

3031
namespace Modelica {
3132

@@ -162,7 +163,11 @@ HorizontalSortingResult HorizontalSorting::sort()
162163
ERROR_UNLESS(num_variables == num_equations, "HorizontalSorting::sort: unbalanced system of equations.\n",
163164
"Number of variables: ", num_variables, "\n", "Number of equations: ", num_equations);
164165

165-
SBG::LIB::MatchData matching_result = SBG::LIB::Matching{}.calculate(bipartite_sbg);
166+
SBG::LIB::MatchData matching_result{SBG::LIB::BipartiteSBG{}, SBG::LIB::Set{}, false};
167+
{
168+
SBG::Util::Internal::TimeProfiler profiler{"Horizontal sorting"};
169+
matching_result = SBG::LIB::Matching{}.calculate(bipartite_sbg);
170+
}
166171
ERROR_UNLESS(matching_result.full_match(), "HorizontalSorting::sort: ", "higher index system");
167172

168173
ModelicaSBG old = _sbg_generation_result.modelica_bsbg();

causalize/sbg_implementation/main.cpp

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -128,27 +128,30 @@ int main(int argc, char** argv)
128128
SBG::LIB::SET_IMPL.set_set_fact(SBG::LIB::SetKind::kOrdUnidimDense);
129129
SBG::LIB::PWMAP_IMPL.set_pwmap_fact(SBG::LIB::PWMapKind::kUnordered);
130130
Modelica::Causalize::CausalizationResult result;
131+
EquationList causalized;
131132
{
132133
SBG::Util::Internal::TimeProfiler profiler{"Causalization"};
133134
result = Modelica::Causalize::Causalize{}.causalize(mmo_class);
134-
}
135-
std::cout << result << "\n";
136135

137-
debugInit("s");
138-
Modelica::AST::ClassList classes = stored_def.classes();
139-
const Modelica::Causalize::CausalModel& causal_model = result.vertical_sort();
140-
EquationList causalized;
141-
Modelica::Causalize::TearingVariables tearing_vars;
142-
if (tearing) {
143-
tearing_vars = result.tearing();
144-
}
145-
for (const Modelica::Causalize::CausalEquations& s : causal_model) {
146-
EquationList res =
147-
EquationSolver::Solve(s.equations(), s.variables(), mmo_class.syms_ref(), mmo_class.variables_ref(), classes, tearing_vars);
148-
causalized.insert(causalized.end(), res.begin(), res.end());
136+
//debugInit("s");
137+
{
138+
SBG::Util::Internal::TimeProfiler solve_profiler{"GiNaC solve"};
139+
Modelica::AST::ClassList classes = stored_def.classes();
140+
const Modelica::Causalize::CausalModel& causal_model = result.vertical_sort();
141+
Modelica::Causalize::TearingVariables tearing_vars;
142+
if (tearing) {
143+
tearing_vars = result.tearing();
144+
}
145+
for (const Modelica::Causalize::CausalEquations& s : causal_model) {
146+
EquationList res =
147+
EquationSolver::Solve(s.equations(), s.variables(), mmo_class.syms_ref(), mmo_class.variables_ref(), classes, tearing_vars);
148+
causalized.insert(causalized.end(), res.begin(), res.end());
149+
}
150+
}
149151
}
150-
151152
mmo_class.equations_ref().equations_ref() = causalized;
153+
154+
std::cout << result << "\n";
152155
std::cout << mmo_class << std::endl;
153156

154157
std::string causalized_file_name = mmo_class.name();
@@ -187,8 +190,15 @@ int main(int argc, char** argv)
187190
}
188191

189192
std::cout << "\n";
193+
SBG::Util::Internal::TimeProfiler::print_execution_time("Horizontal sorting SBG builder");
194+
SBG::Util::Internal::TimeProfiler::print_execution_time("Horizontal sorting");
190195
SBG::Util::Internal::TimeProfiler::print_execution_time("Algebraic loops SBG builder");
191196
SBG::Util::Internal::TimeProfiler::print_execution_time("Algebraic loops detection");
197+
SBG::Util::Internal::TimeProfiler::print_execution_time("Tearing SBG builder");
198+
SBG::Util::Internal::TimeProfiler::print_execution_time("Tearing");
199+
SBG::Util::Internal::TimeProfiler::print_execution_time("Vertical sorting SBG builder");
200+
SBG::Util::Internal::TimeProfiler::print_execution_time("Vertical sorting");
201+
SBG::Util::Internal::TimeProfiler::print_execution_time("GiNaC solve");
192202
SBG::Util::Internal::TimeProfiler::print_execution_time("Causalization");
193203
std::cout << "\n\n";
194204

causalize/sbg_implementation/modelica_sbg.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ namespace Causalize {
3636
*/
3737
class ModelicaSBG {
3838
public:
39+
ModelicaSBG() = default;
3940
ModelicaSBG(std::size_t arity);
4041

4142
std::size_t arity() const;

causalize/sbg_implementation/tearing.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <sbg/directed_sbg.hpp>
3131
#include <sbg/map.hpp>
3232
#include <sbg/set.hpp>
33+
#include <util/time_profiler.hpp>
3334

3435
namespace Modelica {
3536

@@ -97,8 +98,17 @@ TearingDetector::TearingDetector(AlgebraicLoopsResult loops_result) : _loops_res
9798

9899
TearingResult TearingDetector::detect()
99100
{
100-
SBG::LIB::DirectedSBG dsbg = misc::buildTearingSBG(_loops_result.scc_result());
101-
return TearingResult{_loops_result.modelica_bsbg(), SBG::LIB::MinFeedbackVertexSet{}.calculate(dsbg)};
101+
SBG::LIB::DirectedSBG dsbg;
102+
{
103+
SBG::Util::Internal::TimeProfiler profiler{"Tearing SBG builder"};
104+
dsbg = misc::buildTearingSBG(_loops_result.scc_result());
105+
}
106+
SBG::LIB::Set mfvs;
107+
{
108+
SBG::Util::Internal::TimeProfiler profiler{"Tearing"};
109+
mfvs = SBG::LIB::MinFeedbackVertexSet{}.calculate(dsbg);
110+
}
111+
return TearingResult{_loops_result.modelica_bsbg(), mfvs};
102112
}
103113

104114
} // namespace Causalize

causalize/sbg_implementation/vertical_sorting.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <sbg/expression.hpp>
3131
#include <sbg/pw_map.hpp>
3232
#include <sbg/set.hpp>
33+
#include <util/time_profiler.hpp>
3334

3435
#include <algorithm>
3536

@@ -243,10 +244,17 @@ VerticalSorting::VerticalSorting(AlgebraicLoopsResult& loops_result, TearingResu
243244

244245
VerticalSortingResult VerticalSorting::sort()
245246
{
246-
SBG::LIB::DirectedSBG vertical_dsbg = misc::buildVerticalSortingSBG(_loops_result.scc_result(), _tearing_result.mfvs_result());
247-
SBG::LIB::PWMap vertical_sort = SBG::LIB::TopologicalSorting{}.calculate(vertical_dsbg, SBG::LIB::PWMap{});
247+
SBG::LIB::DirectedSBG vertical_dsbg;
248+
{
249+
SBG::Util::Internal::TimeProfiler profiler{"Vertical sorting SBG builder"};
250+
vertical_dsbg = misc::buildVerticalSortingSBG(_loops_result.scc_result(), _tearing_result.mfvs_result());
251+
}
252+
SBG::LIB::PWMap vertical_sort;
253+
{
254+
SBG::Util::Internal::TimeProfiler profiler{"Vertical sorting"};
255+
vertical_sort = SBG::LIB::TopologicalSorting{}.calculate(vertical_dsbg, SBG::LIB::PWMap{});
256+
}
248257

249-
// detectLoop(loops_result)
250258
return VerticalSortingResult{_tearing_result.modelica_bsbg(), vertical_sort};
251259
}
252260

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
################################################################################
22
# Script that executes ../../../bin/causalize 10 times and calculates the
3-
# average times for the algebraic loops and complete causalization phases. It
4-
# repeats these for different values of N = 100, 1000, 10000, 100000 and 1000000
5-
# for each model: TestRL1.mo, TestRL2.mo and TestRL3.mo.
3+
# average times all of the causalization phases, and also the compilation of
4+
# the C generated file. It repeats these for different values of
5+
# N = 100, 1000, 10000, 100000 and 1000000 for each model: TestRL1.mo,
6+
# TestRL2.mo and TestRL3.mo.
67
################################################################################
78

89
import sys
@@ -11,6 +12,15 @@
1112
import os
1213
from collections import defaultdict
1314
from pathlib import Path
15+
import sys
16+
import time
17+
18+
# TODO: erase dummy functions and import QSS actual functions
19+
def mmoc_compile_model(filename):
20+
time.sleep(15 / 1000.0)
21+
22+
def compile_c_model(filename):
23+
time.sleep(15 / 1000.0)
1424

1525
def run_modelicacc_benchmarks(filename, valores_n, runs=10):
1626
try:
@@ -24,6 +34,12 @@ def run_modelicacc_benchmarks(filename, valores_n, runs=10):
2434
print(f"Values of N: {valores_n}")
2535
print(f"Number of runs: {runs}\n")
2636

37+
modelicacc_stages = ["Horizontal sorting SBG builder", "Horizontal sorting"
38+
, "Algebraic loops SBG builder", "Algebraic loops detection"
39+
, "Tearing SBG builder", "Tearing"
40+
, "Vertical sorting SBG builder", "Vertical sorting"
41+
, "GiNaC solve", "Causalization"]
42+
qss_stages = ["ModelicaCC compilation", "C compilation"]
2743
resultados_totales = {}
2844

2945
for n in valores_n:
@@ -41,59 +57,76 @@ def run_modelicacc_benchmarks(filename, valores_n, runs=10):
4157
pattern = re.compile(r"^(.+?):\s*([\d.]+)\s*ms", re.MULTILINE)
4258
fases_tiempos = defaultdict(list)
4359

44-
resultados_totales[n] = {"loops builder": None, "loops": None, "causalize": None}
60+
resultados_totales[n] = dict.fromkeys(modelicacc_stages) | dict.fromkeys(qss_stages)
4561
error_en_este_n = False
4662

4763
for i in range(1, runs + 1):
4864
print(f"Run {i}/{runs}...", end="\r")
65+
# ModelicaCC causalization
4966
try:
5067
result = subprocess.run(command, capture_output=True, text=True, check=True)
5168
output = result.stdout + result.stderr
5269

5370
matches = pattern.findall(output)
5471
for fase, tiempo_str in matches:
55-
if "Algebraic loops SBG builder" in fase:
56-
fases_tiempos["loops builder"].append(float(tiempo_str))
57-
elif "Algebraic loops detection" in fase:
58-
fases_tiempos["loops"].append(float(tiempo_str))
59-
elif "Causalization" in fase:
60-
fases_tiempos["causalize"].append(float(tiempo_str))
72+
fase_clean = fase.strip()
73+
if fase_clean in modelicacc_stages:
74+
fases_tiempos[fase_clean].append(float(tiempo_str))
6175

6276
except subprocess.CalledProcessError as e:
6377
print(f"\nError: ModelicaCC with N={n}, run {i}:")
6478
print(e.stderr)
6579
error_en_este_n = True
6680
break
6781

82+
# QSS compilation
83+
start_time = time.perf_counter()
84+
mmoc_compile_model(filename)
85+
end_time = time.perf_counter()
86+
execution_time = end_time - start_time
87+
fases_tiempos[qss_stages[0]].append(float(execution_time))
88+
89+
start_time = time.perf_counter()
90+
compile_c_model(filename)
91+
end_time = time.perf_counter()
92+
execution_time = end_time - start_time
93+
fases_tiempos[qss_stages[1]].append(float(execution_time))
94+
6895
if os.path.exists(temp_filename):
6996
os.remove(temp_filename)
7097

71-
if error_en_este_n and not fases_tiempos["loops builder"] and not fases_tiempos["loops"] and not fases_tiempos["causalize"]:
98+
if error_en_este_n and not any(fases_tiempos.values()):
7299
print(f"Skipping N={n}.")
73100
continue
74101

75-
for fase in ["loops builder", "loops", "causalize"]:
76-
tiempos = fases_tiempos[fase]
102+
for stage in modelicacc_stages:
103+
tiempos = fases_tiempos[stage]
104+
if tiempos:
105+
resultados_totales[n][stage] = sum(tiempos) / len(tiempos)
106+
107+
for stage in qss_stages:
108+
tiempos = fases_tiempos[stage]
77109
if tiempos:
78-
resultados_totales[n][fase] = sum(tiempos) / len(tiempos)
110+
resultados_totales[n][stage] = sum(tiempos) / len(tiempos)
79111

80112
print("Finished. ")
81113

82114
print(f"\n\n============================== TIME MEASURES: {filename} ==============================")
83-
print(f"{'N':<10} | {'SBG loops builder (ms)':<15} | {'SBG loops detection (ms)':<15} | {'SBG Causalization (ms)':<15}")
84-
print("-" * 87)
115+
print(f"{'N':<10} | {'Stage Name':<35} | {'Average Time (ms)':<20}")
116+
print("-" * 73)
85117

86118
for n in valores_n:
87-
fases = resultados_totales.get(n, {"loops builder": None, "loops": None, "causalize": None})
88-
b_time = fases["loops builder"]
89-
l_time = fases["loops"]
90-
c_time = fases["causalize"]
91-
92-
b_str = f"{b_time:.4e}" if b_time and b_time < 0.001 else (f"{b_time:.6f}" if b_time else "N/A")
93-
l_str = f"{l_time:.4e}" if l_time and l_time < 0.001 else (f"{l_time:.6f}" if l_time else "N/A")
94-
c_str = f"{c_time:.4e}" if c_time and c_time < 0.001 else (f"{c_time:.6f}" if c_time else "N/A")
95-
96-
print(f"{n:<10} | {b_str:<22} | {l_str:<24} | {c_str:<25}")
119+
fases = resultados_totales.get(n, {})
120+
for stage in modelicacc_stages + qss_stages:
121+
tiempo = fases.get(stage)
122+
123+
if tiempo is not None:
124+
t_str = f"{tiempo:.4e}" if tiempo < 0.001 else f"{tiempo:.6f}"
125+
else:
126+
t_str = "N/A"
127+
128+
print(f"{n:<10} | {stage:<35} | {t_str:<20}")
129+
print("-" * 73)
97130
print("=======================================================================================")
98131

99132
if __name__ == "__main__":
@@ -104,7 +137,7 @@ def run_modelicacc_benchmarks(filename, valores_n, runs=10):
104137

105138
input_runs = int(sys.argv[1])
106139

107-
lista_n = [100, 1000, 10000, 100000, 1000000]
140+
lista_n = [10**i for i in range(2, 7)]
108141

109142
model_list = ["TestRL1.mo", "TestRL2.mo", "TestRL3.mo"]
110143
for model in model_list:
@@ -113,16 +146,12 @@ def run_modelicacc_benchmarks(filename, valores_n, runs=10):
113146

114147
directorio_actual = Path(".")
115148

116-
# Contador para saber cuántos archivos se borraron
117-
archivos_eliminados = 0
118-
119149
# Iteramos sobre todos los archivos del directorio
120150
for archivo in directorio_actual.iterdir():
121151
# Verificamos que sea un archivo y que contenga alguno de los dos textos en el nombre
122152
if archivo.is_file() and ("_sbg_input" in archivo.name or "_causalized" in archivo.name):
123153
try:
124154
archivo.unlink() # Elimina el archivo
125155
print(f"Deleted: {archivo.name}")
126-
archivos_eliminados += 1
127156
except Exception as e:
128157
print(f"Unable to delete {archivo.name}: {e}")

0 commit comments

Comments
 (0)