Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RModel.cxx
Go to the documentation of this file.
1#include <limits>
2#include <algorithm>
3#include <cctype>
4#include <memory>
5
6#include "TFile.h"
7
8#include "TMVA/RModel.hxx"
10
11namespace TMVA {
12namespace Experimental {
13namespace SOFIE {
14
15std::underlying_type_t<Options> operator|(Options opA, Options opB) {
16 return static_cast<std::underlying_type_t<Options>>(opA) | static_cast<std::underlying_type_t<Options>>(opB);
17}
18std::underlying_type_t<Options> operator|(std::underlying_type_t<Options> opA, Options opB) {
19 return opA | static_cast<std::underlying_type_t<Options>>(opB);
20}
21
23 fInputTensorInfos = std::move(other.fInputTensorInfos);
24 fReadyInputTensorInfos = std::move(other.fReadyInputTensorInfos);
25 fOutputTensorNames = other.fOutputTensorNames;
26 fInputTensorNames = other.fInputTensorNames;
27 fOperators = std::move(other.fOperators);
28 fInitializedTensors = std::move(other.fInitializedTensors);
29 fIntermediateTensorInfos = std::move(other.fIntermediateTensorInfos);
30 fName = other.fName;
31 fFileName = other.fFileName;
32 fParseTime = other.fParseTime;
33 fGC = other.fGC;
34 fNeededBlasRoutines = other.fNeededBlasRoutines;
35 fNeededStdLib = other.fNeededStdLib;
36}
37
39 fInputTensorInfos = std::move(other.fInputTensorInfos);
40 fReadyInputTensorInfos = std::move(other.fReadyInputTensorInfos);
41 fOutputTensorNames = other.fOutputTensorNames;
42 fInputTensorNames = other.fInputTensorNames;
43 fOperators = std::move(other.fOperators);
44 fInitializedTensors = std::move(other.fInitializedTensors);
45 fIntermediateTensorInfos = std::move(other.fIntermediateTensorInfos);
46 fName = other.fName;
47 fFileName = other.fFileName;
48 fParseTime = other.fParseTime;
49 fGC = other.fGC;
50 fNeededBlasRoutines = other.fNeededBlasRoutines;
51 fNeededStdLib = other.fNeededStdLib;
52 return *this;
53}
54
55const std::vector<size_t>& RModel::GetTensorShape(std::string name) {
56 auto f = fReadyInputTensorInfos.find(name);
57 if (f != fReadyInputTensorInfos.end()) {
58 return f->second.shape;
59 }
60 auto f2 = fInitializedTensors.find(name);
61 if (f2 != fInitializedTensors.end()) {
62 return f2->second.fShape;
63 }
64 auto f3 = fInputTensorInfos.find(name);
65 if (f3 != fInputTensorInfos.end()) {
66 throw std::runtime_error("TMVA SOFIE tensor [" + name + "] is an input tensor with unspecified dimension parameter");
67 }
68 auto f4 = fIntermediateTensorInfos.find(name);
69 if (f4 != fIntermediateTensorInfos.end()) {
70 return f4->second.shape;
71 }
72
73 throw std::runtime_error("TMVA SOFIE tensor [" + name + "] for which the shape is requested is not found");
74}
75
77 auto f = fReadyInputTensorInfos.find(name);
78 if (f != fReadyInputTensorInfos.end()) {
79 return f->second.type;
80 }
81 auto f2 = fInitializedTensors.find(name);
82 if (f2 != fInitializedTensors.end()) {
83 return f2->second.fType;
84 }
85 auto f3 = fInputTensorInfos.find(name);
86 if (f3 != fInputTensorInfos.end()) {
87 return f3->second.type;
88 }
89 auto f4 = fIntermediateTensorInfos.find(name);
90 if (f4 != fIntermediateTensorInfos.end()) {
91 return f4->second.type;
92 }
93
94 throw std::runtime_error("TMVA SOFIE tensor [" + name + "] for which the type is requested is not found");
95}
96
97bool RModel::CheckIfTensorAlreadyExist(std::string tensor_name) {
98 if (fReadyInputTensorInfos.find(tensor_name) != fReadyInputTensorInfos.end()) return true;
99 if (fInitializedTensors.find(tensor_name) != fInitializedTensors.end()) return true;
100 if (fIntermediateTensorInfos.find(tensor_name) != fIntermediateTensorInfos.end()) return true;
101 return false;
102}
103
104void RModel::AddInputTensorInfo(std::string input_name, ETensorType type, std::vector<Dim> shape) {
105 input_name = UTILITY::Clean_name(input_name);
106 if (CheckIfTensorAlreadyExist(input_name)) {
107 throw std::runtime_error("TMVA-SOFIE: input tensor with name " + input_name + " already exists \n");
108 }
109
110 InputTensorInfo inputInfo { type, shape };
111 fInputTensorInfos[input_name] = inputInfo;
112}
113
114void RModel::AddInputTensorInfo(std::string input_name, ETensorType type, std::vector<size_t> shape) {
115 input_name = UTILITY::Clean_name(input_name);
116 if (CheckIfTensorAlreadyExist(input_name)) {
117 throw std::runtime_error("TMVA-SOFIE: input tensor with name " + input_name + " already exists \n");
118 }
119 TensorInfo inputInfo { type, shape };
120 fReadyInputTensorInfos[input_name] = inputInfo;
121}
122
123void RModel::AddInputTensorName(std::string input_name) {
124 fInputTensorNames.push_back(UTILITY::Clean_name(input_name));
125}
126
127void RModel::AddOperator(std::unique_ptr<ROperator> op, int order_execution) {
128 AddBlasRoutines(op->GetBlasRoutines());
129 auto libs = op->GetStdLibs();
130 for (auto& stdlib : libs) {
131 AddNeededStdLib(stdlib);
132 }
133 if (order_execution >= 0) {
134 fOperators.insert(fOperators.begin() + order_execution, std::move(op));
135 } else {
136 fOperators.push_back(std::move(op));
137 }
138}
139
140void RModel::AddInitializedTensor(std::string tensor_name, ETensorType type, std::vector<std::size_t> shape, std::shared_ptr<void> data) {
141 tensor_name = UTILITY::Clean_name(tensor_name);
142 //NB: own data
143 if (CheckIfTensorAlreadyExist(tensor_name)) {
144 throw std::runtime_error("TMVA-SOFIE: initialized tensor with name " + tensor_name + " already exists \n");
145 }
146 InitializedTensor new_tensor {type, shape, data};
147 fInitializedTensors[tensor_name] = new_tensor;
148
149}
150
151bool RModel::IsInitializedTensor(const std::string& tensorName) const {
152 std::string name = UTILITY::Clean_name(tensorName);
153 return fInitializedTensors.find(name) != fInitializedTensors.end();
154}
155
156void RModel::AddIntermediateTensor(std::string tensor_name, ETensorType type, std::vector<std::size_t> shape) {
157 tensor_name = UTILITY::Clean_name(tensor_name);
158 if (CheckIfTensorAlreadyExist(tensor_name)) {
159 throw std::runtime_error("TMVA-SOFIE: intermediate tensor with name " + tensor_name + " already exists \n");
160 }
161 TensorInfo new_tensor {type, shape};
162 fIntermediateTensorInfos[tensor_name] = new_tensor;
163}
164
165void RModel::AddOutputTensorNameList(std::vector<std::string> outputtensornames) {
166 fOutputTensorNames.clear();
167 for(auto& it : outputtensornames) {
169 }
170}
171
172void RModel::UpdateOutputTensorList(std::vector<std::string> curr_output_tensors, std::vector<std::string> new_output_tensors) {
173 for(auto& it:curr_output_tensors) {
174 fOutputTensorNames.erase(std::remove(fOutputTensorNames.begin(), fOutputTensorNames.end(), it), fOutputTensorNames.end());
175 }
176 fOutputTensorNames.insert(fOutputTensorNames.end(), new_output_tensors.begin(), new_output_tensors.end());
177}
178
179void RModel::UpdateInitializedTensor(std::string tensor_name, ETensorType type, std::vector<std::size_t> shape, std::shared_ptr<void> data) {
180 tensor_name = UTILITY::Clean_name(tensor_name);
181 if (!CheckIfTensorAlreadyExist(tensor_name)) {
182 throw std::runtime_error("TMVA-SOFIE: tensor " + tensor_name + " not found when trying to update it");
183 }
184 InitializedTensor new_tensor {type, shape, data};
185 fInitializedTensors[tensor_name] = new_tensor;
186}
187
188std::shared_ptr<void> RModel::GetInitializedTensorData(std::string tensor_name) {
189 auto f = fInitializedTensors.find(tensor_name);
190 if (f == fInitializedTensors.end()) {
191 throw std::runtime_error("TMVA-SOFIE: tensor " + tensor_name + " not found when trying to get its data");
192 } else {
193 return f->second.fData;
194 }
195}
196
197void RModel::Initialize(int batchSize) {
198 // check if there are only parametrized input tensor and convert in
199 // ready input tensor according to batch size
200 // convert parametric shape to a dimensional shape
202 if (fReadyInputTensorInfos.size() != fInputTensorNames.size()) {
203 if ( fReadyInputTensorInfos.size() + fInputTensorInfos.size() != fInputTensorNames.size())
204 throw std::runtime_error("TMVA-SOFIE: RModel::Initializes: invalid inputs");
205 for (auto & input : fInputTensorInfos) {
206 std::vector<size_t> shape;
207 shape.reserve(input.second.shape.size());
208 for (auto & d : input.second.shape) {
209 if (d.isParam)
210 shape.push_back(batchSize);
211 else
212 shape.push_back(d.dim);
213 }
214 AddInputTensorInfo(input.first, input.second.type, shape);
215 }
216 }
217 // check if there are initialized tensors to write in a weight file
218 // support for the time being only weight of FLOAT type
219 if (fUseWeightFile) {
220 bool modelHasWeights = false;
221 for (auto& i: fInitializedTensors) {
222 if (i.second.fType == ETensorType::FLOAT) {
223 modelHasWeights = true;
224 break;
225 }
226 }
227 if (!modelHasWeights) fUseWeightFile = false;
228 }
229
230 for (auto& i : fOperators) {
231 i->Initialize(*this);
232 }
233}
234
236 for (auto& i: fInitializedTensors) {
237 if (i.second.fType == ETensorType::FLOAT) {
238 size_t length = 1;
239 for (auto & dim: i.second.fShape) {
240 length *= dim;
241 }
242 if (!fUseWeightFile) {
243 fGC += "float tensor_" + i.first + "[" + std::to_string(length) + "] = {";
244 std::shared_ptr<float> data = std::static_pointer_cast<float>(i.second.fData);
245 std::stringstream floats;
246 for (size_t idx = 0; idx < length-1; idx++) {
247 floats << std::setprecision(std::numeric_limits<float>::max_digits10) << data.get()[idx] << ", ";
248 }
249 floats << std::setprecision(std::numeric_limits<float>::max_digits10) << data.get()[length-1];
250 fGC += floats.str();
251 fGC += "};\n";
252 }
253 else {
254 fGC += "std::vector<float> fTensor_" + i.first + " = std::vector<float>(" + std::to_string(length) + ");\n";
255 fGC += "float * tensor_" + i.first + " = fTensor_" + i.first + ".data();\n";
256 }
257
258 }
259 }
260}
261
263 for (auto&i: fIntermediateTensorInfos) {
264 size_t length = ConvertShapeToLength(i.second.shape);
265 if (i.second.type == ETensorType::FLOAT) {
266 fGC += "std::vector<float> fTensor_" + i.first + " = std::vector<float>(" + std::to_string(length) + ");\n";
267 fGC += "float * tensor_" + i.first + " = fTensor_" + i.first + ".data();\n";
268 }
269 if (i.second.type == ETensorType::DOUBLE) {
270 fGC += "std::vector<double> fTensor_" + i.first + " = std::vector<double>(" + std::to_string(length) + ");\n";
271 fGC += "double * tensor_" + i.first + " = fTensor_" + i.first + ".data();\n";
272 }
273 if (i.second.type == ETensorType::INT64) {
274 fGC += "std::vector<int64_t> fTensor_" + i.first + " = std::vector<int64_t>(" + std::to_string(length) + ");\n";
275 fGC += "int64_t * tensor_" + i.first + " = fTensor_" + i.first + ".data();\n";
276 }
277 if (i.second.type == ETensorType::BOOL){
278 fGC += "bool tensor_" + i.first + " [" + std::to_string(length) + "] = {false};\n";
279 }
280 }
281}
282
284 size_t outputSize = fOutputTensorNames.size();
285 // assume output types are all the same
286 std::string outputType;
287 if (outputSize == 1) {
289 if (f == fIntermediateTensorInfos.end()) {
290 throw std::runtime_error("TMVA-SOFIE: output tensor " + fOutputTensorNames[0] + " not found when trying to get its info");
291 } else {
292 outputType = ConvertTypeToString(f->second.type);
293 fGC += "std::vector<" + outputType + "> ";
294 }
295 } else {
296 std::vector<ETensorType> outputTensorsTypes(outputSize);
297 for (size_t i = 0; i < outputSize; i++) {
299 if (f == fIntermediateTensorInfos.end()) {
300 throw std::runtime_error("TMVA-SOFIE: output tensor " + fOutputTensorNames[i]
301 + " not found when trying to get its info");
302 } else {
303 outputTensorsTypes[i] = f->second.type;
304 }
305 }
306 // assume all output types are the same
307 outputType = ConvertTypeToString(outputTensorsTypes[0]);
308 for (size_t i = 0; i < outputSize; i++) {
309 if (outputTensorsTypes[i] != outputTensorsTypes[0]) {
310 throw std::runtime_error("TMVA-SOFIE: output tensor " + fOutputTensorNames[i] + " is of different type.");
311 }
312 }
313 fGC += "std::vector<std::vector<" + outputType + ">> ";
314 }
315
316 fGC += "infer(";
317
318 for(size_t i = 0; i<fInputTensorNames.size(); ++i) {
320 case ETensorType::FLOAT : {
321 fGC += "float* tensor_" + fInputTensorNames[i] + ",";
322 break;
323 }
324 case ETensorType::INT32 : {
325 fGC += "int32_t* tensor_" + fInputTensorNames[i] + ",";
326 break;
327 }
328 case ETensorType::INT64 : {
329 fGC += "int64_t* tensor_" + fInputTensorNames[i] + ",";
330 break;
331 }
332 case ETensorType::DOUBLE : {
333 fGC += "double* tensor_" + fInputTensorNames[i] + ",";
334 break;
335 }
336 case ETensorType::BOOL :{
337 fGC += "bool* tensor_" + fInputTensorNames[i] + ",";
338 break;
339 }
340 default: {
341 throw std::runtime_error("TMVA-SOFIE: input tensor " + fInputTensorNames[i] + " is of a data type which is not yet supported.");
342 }
343 }
344 }
345
346 fGC.pop_back(); //remove last ","
347 fGC += "){\n";
348
349 const std::string SP = " ";
350
351 for (size_t id = 0; id < fOperators.size() ; id++) {
352 fGC+= (fOperators[id]->Generate(std::to_string(id)));
353 }
354
355 if (outputSize == 1) {
356 size_t outputLength = ConvertShapeToLength(GetTensorShape(fOutputTensorNames[0]));
357
358 fGC += SP + "std::vector<" + outputType + "> ret (tensor_" + fOutputTensorNames[0] + ", tensor_" + fOutputTensorNames[0] + " + " +
359 std::to_string(outputLength) + ");\n";
360 } else {
361 for (size_t i = 0; i < outputSize; i++) {
362 if (!fOutputTensorNames[i].empty()) {
363 size_t outputLength = ConvertShapeToLength(GetTensorShape(fOutputTensorNames[i]));
364 fGC += SP + "std::vector<" + outputType + "> ret_";
365 fGC += std::to_string(i);
366 fGC += " (tensor_" + fOutputTensorNames[i] + ", tensor_" + fOutputTensorNames[i] + " + " +
367 std::to_string(outputLength) + ");\n";
368 }
369 }
370 fGC += SP + "std::vector<std::vector<" + outputType + ">> ret({";
371 for (size_t i = 0; i < outputSize; i++) {
372 if (fOutputTensorNames[i].empty()) {
373 fGC += "{}";
374 } else {
375 fGC += "ret_";
376 fGC += std::to_string(i);
377 }
378 if (i < outputSize - 1) {
379 fGC += ",";
380 }
381 }
382 fGC += "});\n";
383 }
384 fGC += SP + "return ret;\n";
385 fGC += "}\n";
386}
387
388void RModel::Generate(std::underlying_type_t<Options> options, int batchSize, long pos) {
389 // session flag is used in operator initialize
390 if (static_cast<std::underlying_type_t<Options>>(Options::kNoSession) & options) {
391 fUseSession = false;
393 }
394 if (static_cast<std::underlying_type_t<Options>>(Options::kNoWeightFile) & options) {
395 fUseWeightFile = false;
397 }
398 if (static_cast<std::underlying_type_t<Options>>(Options::kRootBinaryWeightFile) & options) {
399 fUseWeightFile = true;
401 }
402 if (fUseWeightFile && !fUseSession) {
403 throw
404 std::runtime_error("TMVA-SOFIE: RModel::Generate: cannot use a separate weight file without generating a Session class");
405 }
406
407 if (static_cast<std::underlying_type_t<Options>>(Options::kGNN) & options)
408 fIsGNN = true;
409 if (static_cast<std::underlying_type_t<Options>>(Options::kGNNComponent) & options)
410 fIsGNNComponent = true;
411
412 Initialize(batchSize);
413 std::string hgname;
414 if(!fIsGNNComponent) {
415 fGC.clear();
416 GenerateHeaderInfo(hgname);
417 if (fUseSession) {
418 fGC += "struct Session {\n";
419 }
420 }
421
424
425 if (fUseSession) {
426 // add here specific operator code that needs to define session data members
427 fGC += "\n";
428 for (size_t id = 0; id < fOperators.size(); id++) {
429 std::string opName = std::to_string(id);
430 fGC += fOperators[id]->GenerateSessionMembersCode(opName);
431 }
432 fGC += "\n";
433 // here add initialization and reading of weight tensors
434 if (fUseWeightFile) {
435 fGC += "Session(std::string filename =\"\") {\n";
436 fGC += " if (filename.empty()) filename = \"" + fName;
438 fGC += ".dat\";\n";
439 }
441 fGC += ".root\";\n";
442 }
444 //fUseWeightFile = fUseWeightFile;
445 } else {
446 // no need to pass weight file since it is not used
447 // keep passing a string for compatibility
448 fGC += "Session(std::string = \"\") {\n";
449 }
450
451 // add here initialization code
452 for (size_t id = 0; id < fOperators.size() ; id++) {
453 fGC += fOperators[id]->GenerateInitCode();
454 }
455
456 fGC += "}\n\n";
457 }
458
460
461 if(!fIsGNNComponent) {
462 if (fUseSession) {
463 fGC += "};\n";
464 }
465 fGC += ("} //TMVA_SOFIE_" + fName + "\n");
466 fGC += "\n#endif // " + hgname + "\n";
467 }
468}
469
471 // generate the code to read initialized tensors from a text data file
473 if (fInitializedTensors.empty()) return;
474
475 fGC += " std::ifstream f;\n";
476 fGC += " f.open(filename);\n";
477 fGC += " if (!f.is_open()) {\n";
478 fGC += " throw std::runtime_error(\"tmva-sofie failed to open file for input weights\");\n";
479 fGC += " }\n";
480
481 if(fIsGNNComponent) {
482 fGC += " f.seekg(" + std::to_string(pos) + ");\n";
483 }
484
485 fGC += " std::string tensor_name;\n";
486 fGC += " size_t length;\n";
487
488 // loop on tensors and parse the file
489 for (auto& i: fInitializedTensors) {
490 if (i.second.fType == ETensorType::FLOAT) {
491 size_t length = 1;
492 length = ConvertShapeToLength(i.second.fShape);
493 std::string tensor_name = "tensor_" + i.first;
494 std::string slength = std::to_string(length);
495 fGC += " f >> tensor_name >> length;\n";
496 fGC += " if (tensor_name != \"" + tensor_name + "\" ) {\n";
497 fGC += " std::string err_msg = \"TMVA-SOFIE failed to read the correct tensor name; expected name is " +
498 tensor_name + " , read \" + tensor_name;\n";
499 fGC += " throw std::runtime_error(err_msg);\n";
500 fGC += " }\n";
501 fGC += " if (length != " + slength + ") {\n";
502 fGC += " std::string err_msg = \"TMVA-SOFIE failed to read the correct tensor size; expected size is " +
503 slength + " , read \" + std::to_string(length) ;\n";
504 fGC += " throw std::runtime_error(err_msg);\n";
505 fGC += " }\n";
506 fGC += " for (size_t i = 0; i < length; ++i)\n";
507 fGC += " f >> " + tensor_name + "[i];\n";
508 }
509 }
510 fGC += " f.close();\n";
511 }
512
513 // generate the code to read initialized tensors from a ROOT data file
515 fGC += " {\n";
516 fGC += " std::unique_ptr<TFile> rootFile(TFile::Open(filename.c_str(), \"READ\"));\n";
517 fGC += " if (!rootFile->IsOpen()) {\n";
518 fGC += " throw std::runtime_error(\"tmva-sofie failed to open ROOT file for input weights\");\n";
519 fGC += " }\n";
520
521 std::string dirName = fName + "_weights";
522 fGC += " if (!rootFile->GetKey(\"" + dirName + "\")) {\n";
523 fGC += " throw std::runtime_error(\"tmva-sofie failed to open ROOT directory for input weights\");\n";
524 fGC += " }\n";
525
526 for (auto &i : fInitializedTensors) {
527 fGC += " {\n";
528 std::string tensor_name = "tensor_" + i.first;
529 if (i.second.fType == ETensorType::FLOAT) {
530 fGC += " fTensor_" + i.first + " = *reinterpret_cast<std::vector<float>*>(rootFile->Get(\"";
531 fGC += dirName + "/" + tensor_name + "\"));\n";
532 } else if (i.second.fType == ETensorType::DOUBLE) {
533 fGC += " fTensor_" + i.first + " = *reinterpret_cast<std::vector<double>*>(rootFile->Get(\"";
534 fGC += dirName + + "/" + tensor_name + "\"));\n";
535 } else if (i.second.fType == ETensorType::INT64) {
536 fGC += " fTensor_" + i.first + " = *reinterpret_cast<std::vector<int64_t>*>(rootFile->Get(\"";
537 fGC += dirName + "/" + tensor_name + "\"));\n";
538 }
539 fGC += " }\n";
540 }
541 fGC += " }\n";
542 }
543}
544
546 // Determine the file extension based on the weight file type
547 std::string fileExtension;
548 switch (fWeightFile) {
550 fileExtension = ".dat";
551 break;
553 fileExtension = ".root";
554 break;
556 fileExtension = ".dat";
557 break;
558 }
559
560 // If filename is empty, use the model name as the base filename
561 if (filename.empty()) {
562 filename = fFileName + fileExtension;
563 }
564
565 // Write the initialized tensors to the file
567 if(fIsGNNComponent || fIsGNN) {
568 throw std::runtime_error("SOFIE-GNN yet not supports writing to a ROOT file.");
569 }
570 std::unique_ptr<TFile> outputFile(TFile::Open(filename.c_str(), "UPDATE"));
571
572 std::string dirName = fName + "_weights";
573 // check if directory exists, in case delete to replace with new one
574 if (outputFile->GetKey(dirName.c_str()))
575 outputFile->rmdir(dirName.c_str());
576
577 auto outputDir = outputFile->mkdir(dirName.c_str());
578
579 for (const auto& item : fInitializedTensors) {
580 std::string tensorName = "tensor_" + item.first;
581 size_t length = 1;
582 length = ConvertShapeToLength(item.second.fShape);
583 if(item.second.fType == ETensorType::FLOAT) {
584 const std::shared_ptr<void> ptr = item.second.fData; // shared_ptr<void> instance
585 const float* data = (std::static_pointer_cast<float>(item.second.fData)).get();
586 std::vector<float> tensorDataVector(data, data + length);
587 outputDir->WriteObjectAny(&tensorDataVector, "std::vector<float>", tensorName.c_str());
588 }
589 else if(item.second.fType == ETensorType::DOUBLE) {
590 const std::shared_ptr<void> ptr = item.second.fData; // shared_ptr<void> instance
591 const double* data = (std::static_pointer_cast<double>(item.second.fData)).get();
592 std::vector<double> tensorDataVector(data, data + length);
593 outputDir->WriteObjectAny(&tensorDataVector, "std::vector<double>", tensorName.c_str());
594 }
595 else if(item.second.fType == ETensorType::INT64) {
596 const std::shared_ptr<void> ptr = item.second.fData; // shared_ptr<void> instance
597 const int64_t* data = (std::static_pointer_cast<int64_t>(item.second.fData)).get();
598 std::vector<int64_t> tensorDataVector(data, data + length);
599 outputDir->WriteObjectAny(&tensorDataVector, "std::vector<int64_t>", tensorName.c_str());
600 }
601 }
602 outputFile->Write(filename.c_str());
603
604 // this needs to be changed, similar to the text file
605 return -1;
606
607 } else if (fWeightFile == WeightFileType::Text) {
608 std::ofstream f;
609 if(fIsGNNComponent) {
610 // appending all GNN components into the same file
611 f.open(filename, std::ios::app);
612 } else {
613 f.open(filename);
614 }
615 if (!f.is_open())
616 throw
617 std::runtime_error("tmva-sofie failed to open file for tensor weight data");
618 for (auto& i: fInitializedTensors) {
619 if (i.second.fType == ETensorType::FLOAT) {
620 size_t length = 1;
621 for (auto &dim : i.second.fShape) {
622 length *= dim;
623 }
624 std::string tensor_name = "tensor_" + i.first;
625 f << tensor_name << " " << length << "\n";
626 const float * data = (std::static_pointer_cast<float>(i.second.fData)).get();
627 for (size_t idx = 0; idx < length - 1; idx++) {
628 f << std::setprecision(std::numeric_limits<float>::max_digits10) << data[idx] << " ";
629 }
630 f << std::setprecision(std::numeric_limits<float>::max_digits10) << data[length - 1];
631 f << "\n";
632 }
633 }
634 long curr_pos = f.tellp();
635 f.close();
636 return curr_pos;
637 } else {
638 return -1;
639 }
640}
641
643 std::cout << "Model requires following inputs:\n";
644 for (auto& inputInfo: fInputTensorInfos) {
645 std::cout << "Parameterised Tensor name: " << inputInfo.first << "\t";
646 std::cout << "type: " << ConvertTypeToString(inputInfo.second.type) << "\t";
647 std::cout << "shape: [";
648 for (size_t i = 0; i < inputInfo.second.shape.size(); i++) {
649 if (inputInfo.second.shape[i].isParam) {
650 std::cout << inputInfo.second.shape[i].param;
651 } else {
652 std::cout << inputInfo.second.shape[i].dim ;
653 }
654 if (i < inputInfo.second.shape.size() - 1) std::cout << ",";
655 }
656 std::cout << "]" << std::endl;
657 }
658
659 for (auto& inputInfo: fReadyInputTensorInfos) {
660 std::cout << "Fully Specified Tensor name: " << inputInfo.first << "\t";
661 std::cout << "type: " << ConvertTypeToString(inputInfo.second.type) << "\t";
662 std::cout << "shape: [";
663 for (size_t i = 0; i < inputInfo.second.shape.size(); i++) {
664 std::cout << inputInfo.second.shape[i];
665 if (i < inputInfo.second.shape.size() - 1) std::cout << ",";
666 }
667 std::cout << "]" << std::endl;
668 }
669
670}
671
673 std::cout << "Model initialized the following tensors:\n";
674 for (auto& it: fInitializedTensors) {
675 std::cout << "Tensor name: \"" << it.first << "\"\t";
676 std::cout << "type: " << ConvertTypeToString(it.second.fType) << "\t";
677 std::cout << "shape: [";
678 for (size_t i = 0; i < it.second.fShape.size(); i++) {
679 std::cout << it.second.fShape[i];
680 if (i < it.second.fShape.size() - 1) std::cout << ",";
681 }
682 std::cout << "]" << std::endl;
683 }
684}
685
687 std::cout << "Model specify the following intermediate tensors:\n";
688 for (auto& it: fIntermediateTensorInfos) {
689 std::cout << "Tensor name: \"" << it.first << "\"\t";
690 std::cout << "type: " << ConvertTypeToString(it.second.type) << "\t";
691 std::cout << "shape: [";
692 for (size_t i = 0; i < it.second.shape.size(); i++) {
693 std::cout << it.second.shape[i];
694 if (i < it.second.shape.size() - 1) std::cout << ",";
695 }
696 std::cout << "]" << std::endl;
697 }
698}
699
701 std::cout << "Model specify the following output tensors:\n";
702 for (auto& it: fOutputTensorNames) {
703 std::cout << "Tensor name: \"" << it << "\"\t";
704 std::cout << "shape: " << ConvertShapeToString(GetTensorShape(it)) << std::endl;
705 }
706}
707
708void RModel::HeadInitializedTensors(std::string name, int n_print) {
709 auto it = fInitializedTensors.find(name);
710 if (it == fInitializedTensors.end()) {
711 std::cout << "Tensor " << name << " not found in model's intialized tensor list" << std::endl;
712 return;
713 }
714
715 std::cout << "Tensor name: " << it->first << "\t";
716 std::cout << "type: " << ConvertTypeToString(it->second.fType) << "\t";
717 int length =1;
718 std::cout << "shape: [";
719 for (size_t i = 0; i < it->second.fShape.size(); i++) {
720 std::cout << it->second.fShape[i];
721 length *= it->second.fShape[i];
722 if (i < it->second.fShape.size() - 1) std::cout << ",";
723 }
724 std::cout << "]" << std::endl;
725 bool ellipsis = true;
726 if (n_print > length) {
727 n_print = length;
728 ellipsis = false;
729 }
730
731 std::cout << "data: [" << std::endl;
732 if (it->second.fType == ETensorType::FLOAT) {
733 auto converted_data = std::static_pointer_cast<float>(it->second.fData).get();
734 for (int i =0; i < n_print; i++) {
735 std::cout << converted_data[i];
736 if (i < n_print - 1) std::cout << " ,";
737 }
738 }
739 if (ellipsis) std::cout << ", ...";
740 std::cout << "]" << std::endl;
741
742}
743
744void RModel::OutputGenerated(std::string filename, bool append) {
745
747
748 // write weights in a text file
749 if (fUseWeightFile) {
750 if (!filename.empty()) {
751 size_t pos = filename.find(".hxx");
753 filename.replace(pos, 4, ".dat");
755 filename = filename.erase(pos, 4);
756 filename += ".root";
757 }
758 } else {
759 filename = fName;
760 filename += fWeightFile == WeightFileType::Text ? ".dat" : ".root";
761 }
763 }
764}
765
766void RModel::Streamer(TBuffer &R__b) {
767 if (R__b.IsReading()) {
768 RModel::Class()->ReadBuffer(R__b, this);
769 for(auto i=RModel::fInitializedTensors.begin(); i!=RModel::fInitializedTensors.end(); ++i) {
770 i->second.CastPersistentToShared();
771 }
772 }
773 else {
774 for(auto i=RModel::fInitializedTensors.begin(); i!=RModel::fInitializedTensors.end(); ++i) {
775 i->second.CastSharedToPersistent();
776 }
777 RModel::Class()->WriteBuffer(R__b, this);
778 }
779}
780
781}//SOFIE
782}//Experimental
783}//TMVA
#define d(i)
Definition RSha256.hxx:102
#define f(i)
Definition RSha256.hxx:104
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void input
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
Definition TGX11.cxx:110
Buffer base class used for serializing objects.
Definition TBuffer.h:43
Bool_t IsReading() const
Definition TBuffer.h:86
Int_t ReadBuffer(TBuffer &b, void *pointer, Int_t version, UInt_t start, UInt_t count)
Function called by the Streamer functions to deserialize information from buffer b into object at p.
Definition TClass.cxx:6758
Int_t WriteBuffer(TBuffer &b, void *pointer, const char *info="")
Function called by the Streamer functions to serialize object at p to buffer b.
Definition TClass.cxx:6779
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:4070
void GenerateHeaderInfo(std::string &hgname)
std::unordered_set< std::string > fNeededBlasRoutines
void OutputGenerated(std::string filename="", bool append=false)
std::unordered_set< std::string > fNeededStdLib
void AddBlasRoutines(std::vector< std::string > routines)
void AddNeededStdLib(std::string libname)
void AddOutputTensorNameList(std::vector< std::string > outputtensornames)
Definition RModel.cxx:165
const ETensorType & GetTensorType(std::string name)
Definition RModel.cxx:76
void AddIntermediateTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > shape)
Definition RModel.cxx:156
bool CheckIfTensorAlreadyExist(std::string tensor_name)
Definition RModel.cxx:97
std::vector< std::unique_ptr< ROperator > > fOperators
Definition RModel.hxx:23
void OutputGenerated(std::string filename="", bool append=false)
Definition RModel.cxx:744
void AddInputTensorInfo(std::string input_name, ETensorType type, std::vector< Dim > shape)
Definition RModel.cxx:104
void Initialize(int batchSize=1)
Definition RModel.cxx:197
std::unordered_map< std::string, TensorInfo > fIntermediateTensorInfos
Definition RModel.hxx:19
std::unordered_map< std::string, TensorInfo > fReadyInputTensorInfos
Definition RModel.hxx:17
void AddInitializedTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > shape, std::shared_ptr< void > data)
Definition RModel.cxx:140
RModel & operator=(RModel &&other)
Definition RModel.cxx:38
void AddInputTensorName(std::string name)
Definition RModel.cxx:123
std::vector< std::string > fOutputTensorNames
Definition RModel.hxx:20
bool IsInitializedTensor(const std::string &name) const
Definition RModel.cxx:151
void AddOperator(std::unique_ptr< ROperator > op, int order_execution=-1)
Definition RModel.cxx:127
void HeadInitializedTensors(std::string name, int n_print=50)
Definition RModel.cxx:708
const std::vector< size_t > & GetTensorShape(std::string name)
Definition RModel.cxx:55
long WriteInitializedTensorsToFile(std::string filename="")
Definition RModel.cxx:545
void Generate(std::underlying_type_t< Options > options, int batchSize=1, long pos=0)
Definition RModel.cxx:388
std::unordered_map< std::string, InputTensorInfo > fInputTensorInfos
Definition RModel.hxx:16
std::shared_ptr< void > GetInitializedTensorData(std::string tensor_name)
Definition RModel.cxx:188
std::vector< std::string > fInputTensorNames
Definition RModel.hxx:21
std::unordered_map< std::string, InitializedTensor > fInitializedTensors
Definition RModel.hxx:18
void UpdateInitializedTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > shape, std::shared_ptr< void > data)
Definition RModel.cxx:179
void UpdateOutputTensorList(std::vector< std::string > curr_output_tensor, std::vector< std::string > modify_output_tensor)
Definition RModel.cxx:172
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:888
static TClass * Class()
std::string Clean_name(std::string input_tensor_name)
std::string ConvertShapeToString(std::vector< size_t > shape)
std::string ConvertTypeToString(ETensorType type)
std::underlying_type_t< Options > operator|(Options opA, Options opB)
Definition RModel.cxx:15
std::size_t ConvertShapeToLength(std::vector< size_t > shape)
create variable transformations