Skip to content

Commit bd2f22f

Browse files
author
Olia
committed
Time Profiler for Sofie
1 parent 291154b commit bd2f22f

File tree

9 files changed

+262
-33
lines changed

9 files changed

+262
-33
lines changed

tmva/sofie/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(ROOTTMVASofie
2222
TMVA/OperatorList.hxx
2323
TMVA/RModel_Base.hxx
2424
TMVA/RModel.hxx
25+
TMVA/RModelProfiler.hxx
2526
TMVA/ROperator.hxx
2627
TMVA/ROperator_BasicUnary.hxx
2728
TMVA/ROperator_BasicBinary.hxx
@@ -77,6 +78,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(ROOTTMVASofie
7778
SOURCES
7879
src/RModel_Base.cxx
7980
src/RModel.cxx
81+
src/RModelProfiler.cxx
8082
src/RModel_GNN.cxx
8183
src/RModel_GraphIndependent.cxx
8284
src/RFunction.cxx

tmva/sofie/inc/TMVA/RModel.hxx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@ namespace SOFIE {
1111

1212
class RModel final : public RModel_Base {
1313

14+
friend class RModelProfiler;
15+
1416
private:
1517
bool fIsInitialized = false;
1618
bool fIsSubGraph = false;
1719
int fVerbose = 0;
1820
int fBatchSize = -1;
1921
long fReadPos = 0; // reading file position
22+
std::string fProfilerGC = "";
23+
bool fProfile = false;
2024

2125
OptimizationLevel fOptimizationLevel = OptimizationLevel::kExtended;
2226

@@ -131,8 +135,8 @@ public:
131135

132136
void Initialize(int batchSize = -1, bool verbose = false);
133137
void Initialize(const std::map<std::string,size_t> & inputParams, bool verbose = false);
134-
135-
void Generate(std::underlying_type_t<Options> options, int batchSize = -1, long pos = 0, bool verbose = false);
138+
139+
void Generate(std::underlying_type_t<Options> options, int batchSize = -1, long pos = 0, bool verbose = false);
136140
void Generate(Options options = Options::kDefault, int batchSize = -1, int pos = 0, bool verbose = false)
137141
{
138142
Generate(static_cast<std::underlying_type_t<Options>>(options), batchSize, pos, verbose);
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#ifndef TMVA_SOFIE_RMODELPROFILER
2+
#define TMVA_SOFIE_RMODELPROFILER
3+
4+
#include "TMVA/RModel.hxx"
5+
6+
namespace TMVA {
7+
namespace Experimental {
8+
namespace SOFIE {
9+
10+
/// \class RModelProfiler
11+
/// \brief A helper class to generate profiled inference code for an RModel.
12+
///
13+
/// 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.
16+
class RModelProfiler {
17+
private:
18+
RModel &fModel;
19+
20+
void GenerateUtilityFunctions();
21+
22+
public:
23+
// The profiler must be constructed with a model to work on.
24+
RModelProfiler() = delete;
25+
RModelProfiler(RModel &model);
26+
~RModelProfiler() = default;
27+
28+
// There is no point in copying or moving an RModelProfiler
29+
RModelProfiler(const RModelProfiler &other) = delete;
30+
RModelProfiler(RModelProfiler &&other) = delete;
31+
RModelProfiler &operator=(const RModelProfiler &other) = delete;
32+
RModelProfiler &operator=(RModelProfiler &&other) = delete;
33+
34+
// Main function to generate the profiled code.
35+
void Generate();
36+
};
37+
38+
} // namespace SOFIE
39+
} // namespace Experimental
40+
} // namespace TMVA
41+
42+
#endif // TMVA_SOFIE_RMODELPROFILER

tmva/sofie/inc/TMVA/RModel_Base.hxx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ enum class Options {
2626
kRootBinaryWeightFile = 0x4,
2727
kGNN = 0x8,
2828
kGNNComponent = 0x10,
29+
kProfile = 0x20,
2930
};
3031

3132
// Optimization levels inspired by ONNXRuntime.

tmva/sofie/inc/TMVA/ROperator.hxx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ public:
6767
//virtual void Forward_blas() = 0;
6868
virtual ~ROperator(){}
6969

70+
std::string name = "UnnamedOperator";
71+
const std::string &GetOperatorName() { return name; };
72+
7073
protected:
7174
OperatorKind fKind = OperatorKind::UNDEFINED;
7275
size_t fOpOrder = 0;

tmva/sofie/src/RModel.cxx

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#endif
1010

1111
#include "TMVA/RModel.hxx"
12+
#include "TMVA/RModelProfiler.hxx"
1213
#include "TMVA/SOFIE_common.hxx"
1314

1415
namespace TMVA {
@@ -871,7 +872,7 @@ void RModel::GenerateSessionCode()
871872
CheckAndFlushIntermediateMemory(fOperators[op_idx]->GetOpInputTensors(), op_idx);
872873
}
873874

874-
// to check remaining unused fragments after memory allocation (lesser the better)
875+
// to check remaining unused fragments after memory allocation (lesser the better)
875876
// for (const auto &it: fIntermediateMemoryInfo.available_stack){
876877
// std::cout<<"chunk_idx: "<<it.first<<", chunk_size: "<<it.second<<"\n";
877878
// }
@@ -899,13 +900,13 @@ void RModel::GenerateSessionCode()
899900
// Generate code for Session constructor
900901
if (fUseSession) {
901902
std::string sessionName = "Session";
902-
if (fIsSubGraph)
903+
if (fIsSubGraph)
903904
sessionName += "_" + fName;
904905
// add here specific operator code that needs to define session data members
905906
fGC += "\n";
906907
for (size_t id = 0; id < fOperators.size(); id++) {
907908
std::string opName = std::to_string(id);
908-
fGC += fOperators[id]->GenerateSessionMembersCode(opName);
909+
fGC += fOperators[id]->GenerateSessionMembersCode(opName);
909910
}
910911
fGC += "\n";
911912
// here add initialization and reading of weight tensors
@@ -950,35 +951,41 @@ void RModel::GenerateSessionCode()
950951

951952
fGC += "}\n\n";
952953
}
953-
954-
fGC += doInferSignature + "{\n";
955-
fGC += "\n";
956-
957-
// generate the inference code
958-
if (fVerbose)
959-
std::cout << "Generating main inference code for " << fName << std::endl;
960954

961-
if (fOutputTensorNames.size() == 0)
962-
throw std::runtime_error("TMVA-SOFIE: output size=0 are not supported");
955+
if (fProfile) {
956+
RModelProfiler profiler(*this);
957+
profiler.Generate();
958+
fGC += fProfilerGC;
959+
} else {
960+
fGC += doInferSignature + "{\n";
961+
fGC += "\n";
963962

964-
for (size_t op_idx = 0; op_idx < fOperators.size(); ++op_idx) {
963+
// generate the inference code
965964
if (fVerbose)
965+
std::cout << "Generating main inference code for " << fName << std::endl;
966+
967+
if (fOutputTensorNames.size() == 0)
968+
throw std::runtime_error("TMVA-SOFIE: output size=0 are not supported");
969+
970+
for (size_t op_idx = 0; op_idx < fOperators.size(); ++op_idx) {
971+
if (fVerbose)
966972
std::cout << "Generating code for operator .... " << op_idx << std::endl;
967-
fGC += (fOperators[op_idx]->Generate(std::to_string(op_idx)));
968-
}
973+
fGC += (fOperators[op_idx]->Generate(std::to_string(op_idx)));
974+
}
969975

970-
fGC += SP + "using TMVA::Experimental::SOFIE::UTILITY::FillOutput;\n\n";
976+
fGC += SP + "using TMVA::Experimental::SOFIE::UTILITY::FillOutput;\n\n";
971977

972-
for (std::string const &name : fOutputTensorNames) {
973-
// need to check is size is the same (don't want to return a vector with
974-
// larger size) in that case better to copy
975-
bool isIntermediate = fIntermediateTensorInfos.count(name) > 0;
976-
std::string n = isIntermediate ? std::to_string(ConvertShapeToLength(GetTensorShape(name)))
977-
: ConvertDynamicShapeToLength(GetDynamicTensorShape(name));
978-
fGC += SP + "FillOutput(tensor_" + name + ", output_tensor_" + name + ", " + n + ");\n";
979-
}
978+
for (std::string const &name : fOutputTensorNames) {
979+
// need to check is size is the same (don't want to return a vector with
980+
// larger size) in that case better to copy
981+
bool isIntermediate = fIntermediateTensorInfos.count(name) > 0;
982+
std::string n = isIntermediate ? std::to_string(ConvertShapeToLength(GetTensorShape(name)))
983+
: ConvertDynamicShapeToLength(GetDynamicTensorShape(name));
984+
fGC += SP + "FillOutput(tensor_" + name + ", output_tensor_" + name + ", " + n + ");\n";
985+
}
980986

981-
fGC += "}\n\n";
987+
fGC += "}\n\n";
988+
}
982989

983990
// generate the inference overload that returns an output struct
984991
GenerateOutput();
@@ -991,9 +998,11 @@ void RModel::GenerateSessionCode()
991998

992999
void RModel::Generate(std::underlying_type_t<Options> options, int batchSize, long pos, bool verbose)
9931000
{
1001+
bool profile = (options & static_cast<std::underlying_type_t<Options>>(Options::kProfile));
9941002
fVerbose = verbose;
9951003
fBatchSize = batchSize;
9961004
fReadPos = pos;
1005+
fProfile = profile;
9971006

9981007
// session flag is used in operator initialize
9991008
if (static_cast<std::underlying_type_t<Options>>(Options::kNoSession) & options) {
@@ -1013,9 +1022,9 @@ void RModel::Generate(std::underlying_type_t<Options> options, int batchSize, lo
10131022
"TMVA-SOFIE: RModel::Generate: cannot use a separate weight file without generating a Session class");
10141023
}
10151024

1016-
if (static_cast<std::underlying_type_t<Options>>(Options::kGNN) & options)
1025+
if (static_cast<std::underlying_type_t<Options>>(Options::kGNN) & options)
10171026
fIsGNN = true;
1018-
if (static_cast<std::underlying_type_t<Options>>(Options::kGNNComponent) & options)
1027+
if (static_cast<std::underlying_type_t<Options>>(Options::kGNNComponent) & options)
10191028
fIsGNNComponent = true;
10201029

10211030
// initialize the model including all operators and sub-graphs
@@ -1029,13 +1038,13 @@ void RModel::Generate(std::underlying_type_t<Options> options, int batchSize, lo
10291038

10301039
// generate first code for the subgraphs
10311040
for (auto &graph : fSubGraphs) {
1032-
if (fVerbose)
1041+
if (fVerbose)
10331042
std::cout << "generate session code for subgraph " << graph->fName << std::endl;
10341043
graph->GenerateSessionCode();
10351044
fGC += graph->fGC;
10361045
}
10371046

1038-
if (fVerbose)
1047+
if (fVerbose)
10391048
std::cout << "generate Main session code - model " << fName << std::endl;
10401049

10411050
// generate main session code

0 commit comments

Comments
 (0)