Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions tmva/sofie/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(ROOTTMVASofie
TMVA/OperatorList.hxx
TMVA/RModel_Base.hxx
TMVA/RModel.hxx
TMVA/RModelProfiler.hxx
TMVA/ROperator.hxx
TMVA/ROperator_BasicUnary.hxx
TMVA/ROperator_BasicBinary.hxx
Expand Down Expand Up @@ -77,6 +78,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(ROOTTMVASofie
SOURCES
src/RModel_Base.cxx
src/RModel.cxx
src/RModelProfiler.cxx
src/RModel_GNN.cxx
src/RModel_GraphIndependent.cxx
src/RFunction.cxx
Expand Down
8 changes: 6 additions & 2 deletions tmva/sofie/inc/TMVA/RModel.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ namespace SOFIE {

class RModel final : public RModel_Base {

friend class RModelProfiler;

private:
bool fIsInitialized = false;
bool fIsSubGraph = false;
Expand All @@ -20,6 +22,8 @@ private:
size_t fConstantTensorSize = 0; // size (in Bytes) of the allocated constant tensors
size_t fWeightsTensorSize = 0; // size (in Bytes) of the allocated weight tensors
size_t fOtherTensorSize = 0; // size (in Bytes) of intermediate tensors which are not managed by the memory pool
std::string fProfilerGC = "";
bool fProfile = false;

OptimizationLevel fOptimizationLevel = OptimizationLevel::kExtended;

Expand Down Expand Up @@ -151,8 +155,8 @@ public:

void Initialize(int batchSize = -1, bool verbose = false);
void Initialize(const std::map<std::string,size_t> & inputParams, bool verbose = false);

void Generate(std::underlying_type_t<Options> options, int batchSize = -1, long pos = 0, bool verbose = false);
void Generate(std::underlying_type_t<Options> options, int batchSize = -1, long pos = 0, bool verbose = false);
void Generate(Options options = Options::kDefault, int batchSize = -1, int pos = 0, bool verbose = false)
{
Generate(static_cast<std::underlying_type_t<Options>>(options), batchSize, pos, verbose);
Expand Down
42 changes: 42 additions & 0 deletions tmva/sofie/inc/TMVA/RModelProfiler.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#ifndef TMVA_SOFIE_RMODELPROFILER
#define TMVA_SOFIE_RMODELPROFILER

#include "TMVA/RModel.hxx"

namespace TMVA {
namespace Experimental {
namespace SOFIE {

/// \class RModelProfiler
/// \brief A helper class to generate profiled inference code for an RModel.
///
/// This class instruments the generated C++ code to measure the execution
/// time of each operator. It is invoked when the RModel::Generate is called
/// with the Options::kProfile flag.
class RModelProfiler {
private:
RModel &fModel;

void GenerateUtilityFunctions();

public:
// The profiler must be constructed with a model to work on.
RModelProfiler() = delete;
RModelProfiler(RModel &model);
~RModelProfiler() = default;

// There is no point in copying or moving an RModelProfiler
RModelProfiler(const RModelProfiler &other) = delete;
RModelProfiler(RModelProfiler &&other) = delete;
RModelProfiler &operator=(const RModelProfiler &other) = delete;
RModelProfiler &operator=(RModelProfiler &&other) = delete;

// Main function to generate the profiled code.
void Generate();
};

} // namespace SOFIE
} // namespace Experimental
} // namespace TMVA

#endif // TMVA_SOFIE_RMODELPROFILER
1 change: 1 addition & 0 deletions tmva/sofie/inc/TMVA/RModel_Base.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum class Options {
kRootBinaryWeightFile = 0x4,
kGNN = 0x8,
kGNNComponent = 0x10,
kProfile = 0x20,
};

// Optimization levels inspired by ONNXRuntime.
Expand Down
3 changes: 3 additions & 0 deletions tmva/sofie/inc/TMVA/ROperator.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public:
//virtual void Forward_blas() = 0;
virtual ~ROperator(){}

std::string name = "UnnamedOperator";
const std::string &GetOperatorName() { return name; };

protected:

const std::string SP = " "; ///< space used to correctly indent the generated C++ code
Expand Down
49 changes: 29 additions & 20 deletions tmva/sofie/src/RModel.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#endif

#include "TMVA/RModel.hxx"
#include "TMVA/RModelProfiler.hxx"
#include "TMVA/SOFIE_common.hxx"

namespace TMVA {
Expand Down Expand Up @@ -941,7 +942,7 @@ void RModel::GenerateSessionCode()
CheckAndFlushIntermediateMemory(fOperators[op_idx]->GetOpInputTensors(), op_idx);
}

// to check remaining unused fragments after memory allocation (lesser the better)
// to check remaining unused fragments after memory allocation (lesser the better)
// for (const auto &it: fIntermediateMemoryInfo.available_stack){
// std::cout<<"chunk_idx: "<<it.first<<", chunk_size: "<<it.second<<"\n";
// }
Expand Down Expand Up @@ -969,13 +970,13 @@ void RModel::GenerateSessionCode()
// Generate code for Session constructor
if (fUseSession) {
std::string sessionName = "Session";
if (fIsSubGraph)
if (fIsSubGraph)
sessionName += "_" + fName;
// add here specific operator code that needs to define session data members
fGC += "\n";
for (size_t id = 0; id < fOperators.size(); id++) {
std::string opName = std::to_string(id);
fGC += fOperators[id]->GenerateSessionMembersCode(opName);
fGC += fOperators[id]->GenerateSessionMembersCode(opName);
}
fGC += "\n";
// here add initialization and reading of weight tensors
Expand Down Expand Up @@ -1021,23 +1022,28 @@ void RModel::GenerateSessionCode()
fGC += "}\n\n";
}

fGC += doInferSignature + "{\n";
fGC += "\n";
if (fProfile) {
RModelProfiler profiler(*this);
profiler.Generate();
fGC += fProfilerGC;
} else {
fGC += doInferSignature + "{\n";
fGC += "\n";

// generate the inference code
if (fVerbose)
std::cout << "Generating main inference code for " << fName << std::endl;
// generate the inference code
if (fVerbose)
std::cout << "Generating main inference code for " << fName << std::endl;

if (fOutputTensorNames.size() == 0)
throw std::runtime_error("TMVA-SOFIE: output size=0 are not supported");
if (fOutputTensorNames.size() == 0)
throw std::runtime_error("TMVA-SOFIE: output size=0 are not supported");

for (size_t op_idx = 0; op_idx < fOperators.size(); ++op_idx) {
if (fVerbose)
for (size_t op_idx = 0; op_idx < fOperators.size(); ++op_idx) {
if (fVerbose)
std::cout << "Generating code for operator .... " << op_idx << std::endl;
fGC += (fOperators[op_idx]->Generate(std::to_string(op_idx)));
}
fGC += (fOperators[op_idx]->Generate(std::to_string(op_idx)));
}

fGC += SP + "using TMVA::Experimental::SOFIE::UTILITY::FillOutput;\n\n";
fGC += SP + "using TMVA::Experimental::SOFIE::UTILITY::FillOutput;\n\n";

for (std::string const &name : fOutputTensorNames) {
// need to check is size is the same (don't want to return a vector with
Expand All @@ -1048,7 +1054,8 @@ void RModel::GenerateSessionCode()
fGC += SP + "FillOutput(tensor_" + name + ", output_tensor_" + name + ", " + n + ");\n";
}

fGC += "}\n\n";
fGC += "}\n\n";
}

// generate the inference overload that returns an output struct
GenerateOutput();
Expand All @@ -1061,9 +1068,11 @@ void RModel::GenerateSessionCode()

void RModel::Generate(std::underlying_type_t<Options> options, int batchSize, long pos, bool verbose)
{
bool profile = (options & static_cast<std::underlying_type_t<Options>>(Options::kProfile));
fVerbose = verbose;
fBatchSize = batchSize;
fReadPos = pos;
fProfile = profile;

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

if (static_cast<std::underlying_type_t<Options>>(Options::kGNN) & options)
if (static_cast<std::underlying_type_t<Options>>(Options::kGNN) & options)
fIsGNN = true;
if (static_cast<std::underlying_type_t<Options>>(Options::kGNNComponent) & options)
if (static_cast<std::underlying_type_t<Options>>(Options::kGNNComponent) & options)
fIsGNNComponent = true;

// initialize the model including all operators and sub-graphs
Expand All @@ -1099,13 +1108,13 @@ void RModel::Generate(std::underlying_type_t<Options> options, int batchSize, lo

// generate first code for the subgraphs
for (auto &graph : fSubGraphs) {
if (fVerbose)
if (fVerbose)
std::cout << "generate session code for subgraph " << graph->fName << std::endl;
graph->GenerateSessionCode();
fGC += graph->fGC;
}

if (fVerbose)
if (fVerbose)
std::cout << "generate Main session code - model " << fName << std::endl;

// generate main session code
Expand Down
Loading