11namespace Experimental{
52 return f->second.shape;
56 return f2->second.fShape;
60 throw std::runtime_error(
"TMVA SOFIE tensor [" +
name +
"] is an input tensor with unspecified dimension parameter");
64 return f4->second.shape;
67 throw std::runtime_error(
"TMVA SOFIE tensor [" +
name +
"] for which the shape is requested is not found");
73 return f->second.type;
77 return f2->second.fType;
81 return f3->second.type;
85 return f4->second.type;
88 throw std::runtime_error(
"TMVA SOFIE tensor [" +
name +
"] for which the shape is requested is not found");
101 throw std::runtime_error(
"TMVA-SOFIE: input tensor with name " + input_name +
" already exists \n");
111 throw std::runtime_error(
"TMVA-SOFIE: input tensor with name " + input_name +
" already exists \n");
118 if (order_execution >= 0) {
129 throw std::runtime_error(
"TMVA-SOFIE: initialized tensor with name " + tensor_name +
" already exists \n");
139 throw std::runtime_error(
"TMVA-SOFIE: intermediate tensor with name " + tensor_name +
" already exists \n");
146 for(
auto& it : outputtensornames){
154 throw std::runtime_error(
"TMVA-SOFIE: tensor " + tensor_name +
" not found when trying to update it");
163 throw std::runtime_error(
"TMVA-SOFIE: tensor " + tensor_name +
" not found when trying to get its data");
165 return f->second.fData;
171 i->Initialize(*
this);
178 fGC += (
"//Code generated automatically by TMVA for Inference of Model file [" +
fFileName +
"] at [" +
fParseTime.substr(0,
fParseTime.length()-1) +
"] \n");
180 std::string hgname =
fName;
181 std::transform(hgname.begin(), hgname.end(), hgname.begin(), [](
unsigned char c){ return std::toupper(c);} );
182 hgname =
"TMVA_SOFIE_" + hgname;
183 fGC +=
"\n#ifndef " + hgname +
"\n";
184 fGC +=
"#define " + hgname +
"\n\n";
186 fGC +=
"#include<" + i +
">\n";
190 fGC +=
"#include \"TMVA/SOFIE_common.hxx\"\n";
192 fGC +=
"#include <fstream>\n";
194 fGC +=
"\nnamespace TMVA_SOFIE_" +
fName +
"{\n";
196 fGC += (
"namespace BLAS{\n");
198 if (routine ==
"Gemm") {
199 fGC += (
"\textern \"C\" void sgemm_(const char * transa, const char * transb, const int * m, const int * n, const int * k,\n"
200 "\t const float * alpha, const float * A, const int * lda, const float * B, const int * ldb,\n"
201 "\t const float * beta, float * C, const int * ldc);\n");
202 }
else if (routine ==
"Gemv") {
203 fGC += (
"\textern \"C\" void sgemv_(const char * trans, const int * m, const int * n, const float * alpha, const float * A,\n"
204 "\t const int * lda, const float * X, const int * incx, const float * beta, const float * Y, const int * incy);\n");
205 }
else if (routine ==
"Axpy") {
206 fGC += (
"\textern \"C\" void saxpy_(const int * n, const float * alpha, const float * x,\n"
207 "\t const int * incx, float * y, const int * incy);\n");
208 }
else if (routine ==
"Copy") {
209 fGC += (
"\textern \"C\" void scopy_(const int *n, const float* x, const int *incx, float* y, const int* incy);\n");
212 fGC += (
"}//BLAS\n");
215 fGC +=
"struct Session {\n";
220 for (
auto & dim: i.second.fShape){
223 if (!useWeightFile) {
224 fGC +=
"float tensor_" + i.first +
"[" + std::to_string(length) +
"] = {";
225 std::shared_ptr<float> data = std::static_pointer_cast<float>(i.second.fData);
226 std::stringstream floats;
227 for (
size_t idx = 0; idx < length-1; idx++){
228 floats << std::setprecision(std::numeric_limits<float>::max_digits10) << data.get()[idx] <<
", ";
230 floats << std::setprecision(std::numeric_limits<float>::max_digits10) << data.get()[length-1];
235 fGC +=
"std::vector<float> fTensor_" + i.first +
" = std::vector<float>(" + std::to_string(length) +
");\n";
236 fGC +=
"float * tensor_" + i.first +
" = fTensor_" + i.first +
".data();\n";
244 for (
auto & dim: i.second.shape){
248 fGC +=
"std::vector<float> fTensor_" + i.first +
" = std::vector<float>(" + std::to_string(length) +
");\n";
249 fGC +=
"float * tensor_" + i.first +
" = fTensor_" + i.first +
".data();\n";
255 for (
size_t id = 0;
id <
fOperators.size();
id++) {
256 std::string opName = std::to_string(
id);
260 fGC +=
"Session(std::string filename =\"\") {\n";
263 fGC +=
" if (filename.empty()) filename = \"" +
fName +
".dat\";\n";
268 for (
size_t id = 0;
id <
fOperators.size() ;
id++){
275 if (outputSize == 1) {
278 throw std::runtime_error(
"TMVA-SOFIE: output tensor " +
fOutputTensorNames[0] +
" not found when trying to get its info");
281 fGC +=
"std::vector<float> ";
285 std::vector<ETensorType> outputTensorsTypes(outputSize);
286 for (
size_t i = 0; i < outputSize; i++) {
290 +
" not found when trying to get its info");
292 outputTensorsTypes[i] =
f->second.type;
296 for (
size_t i = 0; i < outputSize; i++) {
297 if (outputTensorsTypes[i] != outputType) {
298 throw std::runtime_error(
"TMVA-SOFIE: output tensor " +
fOutputTensorNames[i] +
" is of different type.");
302 fGC +=
"std::vector<std::vector<float>> ";
309 for (
auto& dim: i.second.shape){
313 fGC +=
"float* tensor_" + i.first +
",";
319 for (
size_t id = 0;
id <
fOperators.size() ;
id++){
322 if (outputSize == 1) {
326 std::to_string(outputLength) +
");\n";
328 for (
size_t i = 0; i < outputSize; i++) {
331 fGC +=
"\tstd::vector<float> ret_";
332 fGC += std::to_string(i);
334 std::to_string(outputLength) +
");\n";
337 fGC +=
"\tstd::vector<std::vector<float>> ret({";
338 for (
size_t i = 0; i < outputSize; i++) {
343 fGC += std::to_string(i);
345 if (i < outputSize - 1) {
351 fGC +=
"\treturn ret;\n";
356 fGC += (
"} //TMVA_SOFIE_" +
fName +
"\n");
357 fGC +=
"\n#endif // " + hgname +
"\n";
362 fGC +=
" std::ifstream f;\n";
363 fGC +=
" f.open(filename);\n";
364 fGC +=
" if (!f.is_open()){\n";
365 fGC +=
" throw std::runtime_error(\"tmva-sofie failed to open file for input weights\");\n";
367 fGC +=
" std::string tensor_name;\n";
368 fGC +=
" int length;\n";
374 for (
auto & dim: i.second.fShape){
377 std::string tensor_name =
"tensor_" + i.first;
378 std::string slength = std::to_string(length);
379 fGC +=
" f >> tensor_name >> length;\n";
380 fGC +=
" if (tensor_name != \"" + tensor_name +
"\" ) {\n";
381 fGC +=
" std::string err_msg = \"TMVA-SOFIE failed to read the correct tensor name; expected name is " +
382 tensor_name +
" , read \" + tensor_name;\n";
383 fGC +=
" throw std::runtime_error(err_msg);\n";
385 fGC +=
" if (length != " + slength +
") {\n";
386 fGC +=
" std::string err_msg = \"TMVA-SOFIE failed to read the correct tensor size; expected size is " +
387 slength +
" , read \" + std::to_string(length) ;\n";
388 fGC +=
" throw std::runtime_error(err_msg);\n";
390 fGC +=
" for (int i =0; i < length; ++i) \n";
391 fGC +=
" f >> " + tensor_name +
"[i];\n";
394 fGC +=
" f.close();\n";
400 filename =
fName +
".data";
406 throw std::runtime_error(
"tmva-sofie failed to open file for tensor weight data");
411 for (
auto &dim : i.second.fShape) {
414 std::string tensor_name =
"tensor_" + i.first;
415 f << tensor_name <<
" " << length <<
"\n";
416 const float * data = (std::static_pointer_cast<float>(i.second.fData)).get();
417 for (
size_t idx = 0; idx < length - 1; idx++) {
418 f << std::setprecision(std::numeric_limits<float>::max_digits10) << data[idx] <<
" ";
420 f << std::setprecision(std::numeric_limits<float>::max_digits10) << data[length - 1];
428 std::cout <<
"Model requires following inputs:\n";
430 std::cout <<
"Parameterised Tensor name: " << inputInfo.first <<
"\t";
432 std::cout <<
"shape: [";
433 for (
size_t i = 0; i < inputInfo.second.shape.size(); i++){
434 if (inputInfo.second.shape[i].isParam){
435 std::cout << inputInfo.second.shape[i].param;
437 std::cout << inputInfo.second.shape[i].dim ;
439 if (i < inputInfo.second.shape.size() - 1) std::cout <<
",";
441 std::cout <<
"]" << std::endl;
445 std::cout <<
"Fully Specified Tensor name: " << inputInfo.first <<
"\t";
447 std::cout <<
"shape: [";
448 for (
size_t i = 0; i < inputInfo.second.shape.size(); i++){
449 std::cout << inputInfo.second.shape[i];
450 if (i < inputInfo.second.shape.size() - 1) std::cout <<
",";
452 std::cout <<
"]" << std::endl;
458 std::cout <<
"Model initialized the following tensors:\n";
460 std::cout <<
"Tensor name: \"" << it.first <<
"\"\t";
462 std::cout <<
"shape: [";
463 for (
size_t i = 0; i < it.second.fShape.size(); i++){
464 std::cout << it.second.fShape[i];
465 if (i < it.second.fShape.size() - 1) std::cout <<
",";
467 std::cout <<
"]" << std::endl;
472 std::cout <<
"Model specify the following intermediate tensors:\n";
474 std::cout <<
"Tensor name: \"" << it.first <<
"\"\t";
476 std::cout <<
"shape: [";
477 for (
size_t i = 0; i < it.second.shape.size(); i++){
478 std::cout << it.second.shape[i];
479 if (i < it.second.shape.size() - 1) std::cout <<
",";
481 std::cout <<
"]" << std::endl;
488 std::cout <<
"Tensor " <<
name <<
" not found in model's intiialized tensor list" << std::endl;
492 std::cout <<
"Tensor name: " << it->first <<
"\t";
495 std::cout <<
"shape: [";
496 for (
size_t i = 0; i < it->second.fShape.size(); i++){
497 std::cout << it->second.fShape[i];
498 length *= it->second.fShape[i];
499 if (i < it->second.fShape.size() - 1) std::cout <<
",";
501 std::cout <<
"]" << std::endl;
502 bool ellipsis =
true;
503 if (n_print > length){
508 std::cout <<
"data: [" << std::endl;
512 auto converted_data = std::static_pointer_cast<float>(it->second.fData).get();
513 for (
int i =0; i < n_print; i++){
514 std::cout << converted_data[i];
515 if (i < n_print - 1) std::cout <<
" ,";
520 if (ellipsis) std::cout <<
", ...";
521 std::cout <<
"]" << std::endl;
527 filename =
fName +
".hxx";
532 throw std::runtime_error(
"tmva-sofie failed to open file for output generated inference code");
538 size_t pos = filename.find(
".hxx");
539 filename.replace(pos,4,
".dat");
543 void RModel::Streamer(
TBuffer &R__b){
545 RModel::Class()->ReadBuffer(R__b,
this);
547 i->second.CastPersistentToShared();
552 i->second.CastSharedToPersistent();
554 RModel::Class()->WriteBuffer(R__b,
this);
Buffer base class used for serializing objects.
void AddOutputTensorNameList(std::vector< std::string > outputtensornames)
void ReadInitializedTensorsFromFile()
const ETensorType & GetTensorType(std::string name)
void Generate(bool useSession=true, bool useWeightFile=true)
void PrintIntermediateTensors()
void AddIntermediateTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > shape)
std::unordered_set< std::string > fNeededBlasRoutines
bool CheckIfTensorAlreadyExist(std::string tensor_name)
std::vector< std::unique_ptr< ROperator > > fOperators
void AddInputTensorInfo(std::string input_name, ETensorType type, std::vector< Dim > shape)
std::unordered_map< std::string, TensorInfo > fIntermediateTensorInfos
std::unordered_map< std::string, TensorInfo > fReadyInputTensorInfos
void AddInitializedTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > shape, std::shared_ptr< void > data)
RModel & operator=(RModel &&other)
std::vector< std::string > fOutputTensorNames
std::unordered_set< std::string > fNeededStdLib
void PrintInitializedTensors()
void AddOperator(std::unique_ptr< ROperator > op, int order_execution=-1)
void HeadInitializedTensors(std::string name, int n_print=50)
void OutputGenerated(std::string filename="")
const std::vector< size_t > & GetTensorShape(std::string name)
std::unordered_map< std::string, InputTensorInfo > fInputTensorInfos
std::shared_ptr< void > GetInitializedTensorData(std::string tensor_name)
void WriteInitializedTensorsToFile(std::string filename="")
std::unordered_map< std::string, InitializedTensor > fInitializedTensors
void UpdateInitializedTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > shape, std::shared_ptr< void > data)
void PrintRequiredInputTensors()
std::string Clean_name(std::string input_tensor_name)
std::string ConvertTypeToString(ETensorType type)
std::size_t ConvertShapeToLength(std::vector< size_t > shape)
create variable transformations