Skip to content

Commit 58b566e

Browse files
committed
[tmva][sofie] Apply fixes after rebasing to master olha profiler branch
Split generation of code of RModelProfiler in different funcitons to make it more indipendent of RModel and the rest of teh code generation. This was needed to take into account many changes in the code performed to make the Sofie generated code understantable by Clad for AD. Fix also a compiler warning due to the name of ROperator.
1 parent 4cb5ffd commit 58b566e

6 files changed

Lines changed: 77 additions & 118 deletions

File tree

tmva/sofie/inc/TMVA/RModel.hxx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ private:
2727
size_t fWeightsTensorSize = 0; // size (in Bytes) of the allocated weight tensors
2828
size_t fOtherTensorSize = 0; // size (in Bytes) of intermediate tensors which are not managed by the memory pool
2929

30-
std::string fProfilerGC = "";
31-
3230
OptimizationLevel fOptimizationLevel = OptimizationLevel::kExtended;
3331

3432
std::unordered_map<std::string, InputTensorInfo> fInputTensorInfos; // input tensors where shape may not fully defined or other graph inputs?

tmva/sofie/inc/TMVA/RModelProfiler.hxx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,28 @@ namespace SOFIE {
1111
/// \brief A helper class to generate profiled inference code for an RModel.
1212
///
1313
/// This class instruments the generated C++ code to measure the execution
14-
/// time of each operator. It is invoked when the RModel::Generate is called
15-
/// with the Options::kProfile flag.
14+
/// time of each operator. The functions are invoked when the RModel::Generate is called
15+
/// with the Options::kProfile flag.
1616
class RModelProfiler {
17-
private:
18-
RModel &fModel;
19-
20-
void GenerateUtilityFunctions();
2117

2218
public:
23-
// The profiler must be constructed with a model to work on.
19+
static void AddNeededStdLibs(RModel &model);
20+
static std::string GenerateUtilityFunctions();
21+
static std::string GenerateSessionMembers();
22+
static std::string GenerateBeginInferCode();
23+
static std::string GenerateOperatorCode(ROperator &op, size_t op_idx);
24+
static std::string GenerateEndInferCode();
25+
26+
2427
RModelProfiler() = delete;
25-
RModelProfiler(RModel &model);
2628
~RModelProfiler() = default;
27-
29+
2830
// There is no point in copying or moving an RModelProfiler
2931
RModelProfiler(const RModelProfiler &other) = delete;
3032
RModelProfiler(RModelProfiler &&other) = delete;
3133
RModelProfiler &operator=(const RModelProfiler &other) = delete;
3234
RModelProfiler &operator=(RModelProfiler &&other) = delete;
33-
34-
// Main function to generate the profiled code.
35-
void Generate();
35+
3636
};
3737

3838
} // namespace SOFIE

tmva/sofie/inc/TMVA/ROperator.hxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ public:
4040
//virtual void Forward_blas() = 0;
4141
virtual ~ROperator(){}
4242

43-
std::string name = "UnnamedOperator";
44-
const std::string &GetOperatorName() { return name; };
43+
std::string fName = "UnnamedOperator";
44+
const std::string & Name() const { return fName; };
4545

4646
protected:
4747

tmva/sofie/src/RModel.cxx

Lines changed: 23 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,10 @@ void RModel::Initialize(const std::map<std::string, size_t> & inputParams, bool
703703
}
704704
}
705705

706+
if (fProfile) {
707+
RModelProfiler::AddNeededStdLibs(*this);
708+
}
709+
706710
fIsInitialized = true;
707711
}
708712

@@ -1280,7 +1284,10 @@ void RModel::GenerateSessionCode()
12801284
GenerateIntermediateTensorInfo();
12811285
// generate code for declarations of some specific operators
12821286
GenerateOperatorDeclarations();
1283-
1287+
// generate code for profiling if enabled
1288+
if (fProfile) {
1289+
fGC += RModelProfiler::GenerateSessionMembers();
1290+
}
12841291
// storing the parameters for future checking to avoid mismatches
12851292
if (!fDimShapeNames.empty()) {
12861293
fGC += "\n\n";
@@ -1298,9 +1305,6 @@ void RModel::GenerateSessionCode()
12981305

12991306
// Generate code for Session constructor
13001307
if (fUseSession) {
1301-
std::string sessionName = "Session";
1302-
if (fIsSubGraph)
1303-
sessionName += "_" + fName;
13041308
// add here specific operator code that needs to define session data members
13051309
fGC += "\n";
13061310
for (size_t id = 0; id < fOperators.size(); id++) {
@@ -1371,10 +1375,8 @@ void RModel::GenerateSessionCode()
13711375
}
13721376

13731377
if (fProfile) {
1374-
RModelProfiler profiler(*this);
1375-
profiler.Generate();
1376-
fGC += fProfilerGC;
1377-
} else {
1378+
fGC += RModelProfiler::GenerateUtilityFunctions();
1379+
}
13781380

13791381
fGC += doInferSignature + " {\n";
13801382
fGC += "\n";
@@ -1386,54 +1388,31 @@ void RModel::GenerateSessionCode()
13861388
if (fOutputTensorNames.size() == 0)
13871389
throw std::runtime_error("TMVA-SOFIE: output size=0 are not supported");
13881390

1391+
if (fProfile) {
1392+
fGC += RModelProfiler::GenerateBeginInferCode();
1393+
}
1394+
13891395
std::string allOperatorCode;
13901396

13911397
for (size_t op_idx = 0; op_idx < fOperators.size(); ++op_idx) {
1392-
if (fVerbose)
1398+
if (fVerbose) {
13931399
std::cout << "Generating code for operator .... " << op_idx << std::endl;
1394-
std::string operatorCode = fOperators[op_idx]->Generate(std::to_string(op_idx));
1395-
allOperatorCode += operatorCode;
1400+
}
1401+
if (fProfile) {
1402+
allOperatorCode += RModelProfiler::GenerateOperatorCode(*fOperators[op_idx], op_idx);
1403+
} else {
1404+
allOperatorCode += fOperators[op_idx]->Generate(std::to_string(op_idx));
1405+
}
13961406
}
13971407

13981408
// If the generated code users members of the session struct, use the
13991409
// local variable name that we're using for the session:
14001410
ReplaceAll(allOperatorCode, "this->", "session.");
14011411

1412+
if (fProfile) {
1413+
fGC += RModelProfiler::GenerateEndInferCode();
14021414
}
14031415

1404-
// fGC += doInferSignature + "{\n";
1405-
// fGC += "\n";
1406-
1407-
// // generate the inference code
1408-
// if (fVerbose)
1409-
// std::cout << "Generating main inference code for " << fName << std::endl;
1410-
1411-
// if (fOutputTensorNames.size() == 0)
1412-
// throw std::runtime_error("TMVA-SOFIE: output size=0 are not supported");
1413-
1414-
// for (size_t op_idx = 0; op_idx < fOperators.size(); ++op_idx) {
1415-
// if (fVerbose)
1416-
// std::cout << "Generating code for operator .... " << op_idx << std::endl;
1417-
// fGC += (fOperators[op_idx]->Generate(std::to_string(op_idx)));
1418-
// }
1419-
1420-
// fGC += SP + "using TMVA::Experimental::SOFIE::UTILITY::FillOutput;\n\n";
1421-
1422-
// for (std::string const &name : fOutputTensorNames) {
1423-
// // need to check is size is the same (don't want to return a vector with
1424-
// // larger size) in that case better to copy
1425-
// bool isIntermediate = fIntermediateTensorInfos.count(name) > 0;
1426-
// std::string n = isIntermediate ? std::to_string(ConvertShapeToLength(GetTensorShape(name)))
1427-
// : ConvertDimShapeToLength(GetDimTensorShape(name));
1428-
// fGC += SP + "FillOutput(tensor_" + name + ", output_tensor_" + name + ", " + n + ");\n";
1429-
// }
1430-
1431-
// fGC += "}\n\n";
1432-
// }
1433-
1434-
// // generate the inference overload that returns an output struct
1435-
// GenerateOutput();
1436-
14371416
// end of session
14381417
if (fUseSession && !fIsGNNComponent) {
14391418
// Collect all "tensor_*" data members that are not input or output tensors

tmva/sofie/src/RModelProfiler.cxx

Lines changed: 37 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,20 @@ namespace Experimental {
66
namespace SOFIE {
77

88
// The constructor now just registers the necessary C++ libraries.
9-
RModelProfiler::RModelProfiler(RModel &model) : fModel(model)
9+
void RModelProfiler::AddNeededStdLibs(RModel &model)
1010
{
11-
fModel.AddNeededStdLib("chrono"); // for timing operators
12-
fModel.AddNeededStdLib("vector"); // for storing profiling results
13-
fModel.AddNeededStdLib("string"); // for operator names
14-
fModel.AddNeededStdLib("map"); // for the results map
15-
fModel.AddNeededStdLib("iostream"); // for printing results
16-
fModel.AddNeededStdLib("iomanip"); // for printing results
11+
model.AddNeededStdLib("chrono"); // for timing operators
12+
model.AddNeededStdLib("vector"); // for storing profiling results
13+
model.AddNeededStdLib("string"); // for operator names
14+
model.AddNeededStdLib("map"); // for the results map
15+
model.AddNeededStdLib("iostream"); // for printing results
16+
model.AddNeededStdLib("iomanip"); // for printing results
1717
}
1818

1919
// This function generates the helper functions inside the Session struct.
20-
void RModelProfiler::GenerateUtilityFunctions()
20+
std::string RModelProfiler::GenerateUtilityFunctions()
2121
{
22-
auto &gc = fModel.fProfilerGC;
22+
std::string gc;
2323

2424
// Generate PrintProfilingResults function
2525
gc += " // generate code for printing operator results. By default order according to time (from higher to lower)\n";
@@ -107,68 +107,50 @@ void RModelProfiler::GenerateUtilityFunctions()
107107
gc += "\n";
108108
gc += " return variance;\n";
109109
gc += " }\n";
110+
111+
return gc;
110112
}
111113

114+
// Generate code for adding session member
115+
112116
// Main generation function for the profiler.
113-
void RModelProfiler::Generate()
117+
std::string RModelProfiler::GenerateSessionMembers()
114118
{
115-
// Clear the profiler's code string to start fresh.
116-
fModel.fProfilerGC.clear();
117-
auto &gc = fModel.fProfilerGC;
118-
119-
// 1. Add the data member to the Session struct to store results.
120-
gc += "public:\n";
119+
std::string gc;
121120
gc += " // Maps an operator name to a vector of its execution times (in microseconds).\n";
122121
gc += " std::map<std::string, std::vector<double>> fProfilingResults;\n\n";
123-
124-
// 2. Generate and add the utility functions like PrintProfilingResults.
125-
GenerateUtilityFunctions();
126-
127-
// 3. Generate the signature for the profiled doInfer method.
128-
std::string doInferSignature = fModel.GenerateInferSignature();
129-
if (!doInferSignature.empty()) doInferSignature += ", ";
130-
for (auto const &name : fModel.GetOutputTensorNames()) {
131-
doInferSignature += " std::vector<" + ConvertTypeToString(fModel.GetTensorType(name)) + "> &output_tensor_" + name + ",";
132-
}
133-
if (!fModel.GetOutputTensorNames().empty()) {
134-
doInferSignature.back() = ' ';
135-
}
136-
gc += "void doInfer(" + doInferSignature + ") {\n";
137-
138-
// 4. Generate the body of the doInfer method with timing instrumentation.
122+
return gc;
123+
}
124+
std::string RModelProfiler::GenerateBeginInferCode() {
125+
std::string gc;
126+
// 1. Add necessary code for instrumenting with timers
139127
gc += " // Timer variable for profiling\n";
140128
gc += " std::chrono::steady_clock::time_point tp_start, tp_overall_start;\n\n";
141129
gc += " tp_overall_start = std::chrono::steady_clock::now();\n\n";
130+
return gc;
131+
}
132+
std::string RModelProfiler::GenerateOperatorCode(ROperator &op, size_t op_idx) {
133+
std::string gc;
134+
gc += " // -- Profiling for operator " + op.Name() + " --\n";
135+
gc += " tp_start = std::chrono::steady_clock::now();\n\n";
142136

143-
for (size_t op_idx = 0; op_idx < fModel.fOperators.size(); ++op_idx) {
144-
const auto& op = fModel.fOperators[op_idx];
145-
gc += " // -- Profiling for operator " + op->name + " --\n";
146-
gc += " tp_start = std::chrono::steady_clock::now();\n\n";
147-
148-
// Add the actual operator inference code
149-
gc += op->Generate(std::to_string(op_idx));
150-
151-
// Add the code to stop the timer and store the result
152-
gc += "\n fProfilingResults[\"" + op->name + "\"].push_back(\n";
153-
gc += " std::chrono::duration_cast<std::chrono::duration<double, std::micro>>(\n";
154-
gc += " std::chrono::steady_clock::now() - tp_start).count());\n\n";
155-
}
137+
// Add the actual operator inference code
138+
gc += op.Generate(std::to_string(op_idx));
156139

157-
// 5. Generate the code to fill the output tensors.
158-
gc += " using TMVA::Experimental::SOFIE::UTILITY::FillOutput;\n\n";
159-
for (std::string const &name : fModel.GetOutputTensorNames()) {
160-
bool isIntermediate = fModel.fIntermediateTensorInfos.count(name) > 0;
161-
std::string n = isIntermediate ? std::to_string(ConvertShapeToLength(fModel.GetTensorShape(name)))
162-
: ConvertDynamicShapeToLength(fModel.GetDynamicTensorShape(name));
163-
gc += " FillOutput(tensor_" + name + ", output_tensor_" + name + ", " + n + ");\n";
164-
}
140+
// Add the code to stop the timer and store the result
141+
gc += "\n fProfilingResults[\"" + op.Name() + "\"].push_back(\n";
142+
gc += " std::chrono::duration_cast<std::chrono::duration<double, std::micro>>(\n";
143+
gc += " std::chrono::steady_clock::now() - tp_start).count());\n\n";
144+
return gc;
145+
}
165146

147+
std::string RModelProfiler::GenerateEndInferCode() {
148+
std::string gc;
166149
gc += "\n // -- Record overall inference time --\n";
167150
gc += " fProfilingResults[\"Overall_Time\"].push_back(\n";
168151
gc += " std::chrono::duration_cast<std::chrono::duration<double, std::micro>>(\n";
169152
gc += " std::chrono::steady_clock::now() - tp_overall_start).count());\n";
170-
171-
gc += "}\n\n"; // End of doInfer function
153+
return gc;
172154
}
173155

174156
} // namespace SOFIE

tmva/sofie_parsers/src/RModelParser_ONNX.cxx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -883,9 +883,9 @@ void RModelParser_ONNX::ParseONNXGraph(RModel & rmodel, const onnx::GraphProto &
883883
continue;
884884
}
885885
const auto &nodeproto = graph.node(nodesOrder[i]);
886-
op->name = nodeproto.name();
887-
if (op->name.empty()) {
888-
op->name = op_type + "_" + std::to_string(i);
886+
op->fName = nodeproto.name();
887+
if (op->fName.empty()) {
888+
op->fName = op_type + "_" + std::to_string(i);
889889
}
890890

891891
rmodel.AddOperator(std::move(op), node_order_exec++);

0 commit comments

Comments
 (0)