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 }
278}
279
281 size_t outputSize = fOutputTensorNames.size();
282 // assume output types are all the same
283 std::string outputType;
284 if (outputSize == 1) {
286 if (f == fIntermediateTensorInfos.end()) {
287 throw std::runtime_error("TMVA-SOFIE: output tensor " + fOutputTensorNames[0] + " not found when trying to get its info");
288 } else {
289 outputType = ConvertTypeToString(f->second.type);
290 fGC += "std::vector<" + outputType + "> ";
291 }
292 } else {
293 std::vector<ETensorType> outputTensorsTypes(outputSize);
294 for (size_t i = 0; i < outputSize; i++) {
296 if (f == fIntermediateTensorInfos.end()) {
297 throw std::runtime_error("TMVA-SOFIE: output tensor " + fOutputTensorNames[i]
298 + " not found when trying to get its info");
299 } else {
300 outputTensorsTypes[i] = f->second.type;
301 }
302 }
303 // assume all output types are the same
304 outputType = ConvertTypeToString(outputTensorsTypes[0]);
305 for (size_t i = 0; i < outputSize; i++) {
306 if (outputTensorsTypes[i] != outputTensorsTypes[0]) {
307 throw std::runtime_error("TMVA-SOFIE: output tensor " + fOutputTensorNames[i] + " is of different type.");
308 }
309 }
310 fGC += "std::vector<std::vector<" + outputType + ">> ";
311 }
312
313 fGC += "infer(";
314
315 for(size_t i = 0; i<fInputTensorNames.size(); ++i) {
317 case ETensorType::FLOAT : {
318 fGC += "float* tensor_" + fInputTensorNames[i] + ",";
319 break;
320 }
321 case ETensorType::INT32 : {
322 fGC += "int32_t* tensor_" + fInputTensorNames[i] + ",";
323 break;
324 }
325 case ETensorType::INT64 : {
326 fGC += "int64_t* tensor_" + fInputTensorNames[i] + ",";
327 break;
328 }
329 case ETensorType::DOUBLE : {
330 fGC += "double* tensor_" + fInputTensorNames[i] + ",";
331 break;
332 }
333 default: {
334 throw std::runtime_error("TMVA-SOFIE: input tensor " + fInputTensorNames[i] + " is of a data type which is not yet supported.");
335 }
336 }
337 }
338
339 fGC.pop_back(); //remove last ","
340 fGC += "){\n";
341
342 const std::string SP = " ";
343
344 for (size_t id = 0; id < fOperators.size() ; id++) {
345 fGC+= (fOperators[id]->Generate(std::to_string(id)));
346 }
347
348 if (outputSize == 1) {
349 size_t outputLength = ConvertShapeToLength(GetTensorShape(fOutputTensorNames[0]));
350
351 fGC += SP + "std::vector<" + outputType + "> ret (tensor_" + fOutputTensorNames[0] + ", tensor_" + fOutputTensorNames[0] + " + " +
352 std::to_string(outputLength) + ");\n";
353 } else {
354 for (size_t i = 0; i < outputSize; i++) {
355 if (!fOutputTensorNames[i].empty()) {
356 size_t outputLength = ConvertShapeToLength(GetTensorShape(fOutputTensorNames[i]));
357 fGC += SP + "std::vector<" + outputType + "> ret_";
358 fGC += std::to_string(i);
359 fGC += " (tensor_" + fOutputTensorNames[i] + ", tensor_" + fOutputTensorNames[i] + " + " +
360 std::to_string(outputLength) + ");\n";
361 }
362 }
363 fGC += SP + "std::vector<std::vector<" + outputType + ">> ret({";
364 for (size_t i = 0; i < outputSize; i++) {
365 if (fOutputTensorNames[i].empty()) {
366 fGC += "{}";
367 } else {
368 fGC += "ret_";
369 fGC += std::to_string(i);
370 }
371 if (i < outputSize - 1) {
372 fGC += ",";
373 }
374 }
375 fGC += "});\n";
376 }
377 fGC += SP + "return ret;\n";
378 fGC += "}\n";
379}
380
381void RModel::Generate(std::underlying_type_t<Options> options, int batchSize, long pos) {
382 // session flag is used in operator initialize
383 if (static_cast<std::underlying_type_t<Options>>(Options::kNoSession) & options) {
384 fUseSession = false;
386 }
387 if (static_cast<std::underlying_type_t<Options>>(Options::kNoWeightFile) & options) {
388 fUseWeightFile = false;
390 }
391 if (static_cast<std::underlying_type_t<Options>>(Options::kRootBinaryWeightFile) & options) {
392 fUseWeightFile = true;
394 }
395 if (fUseWeightFile && !fUseSession) {
396 throw
397 std::runtime_error("TMVA-SOFIE: RModel::Generate: cannot use a separate weight file without generating a Session class");
398 }
399
400 if (static_cast<std::underlying_type_t<Options>>(Options::kGNN) & options)
401 fIsGNN = true;
402 if (static_cast<std::underlying_type_t<Options>>(Options::kGNNComponent) & options)
403 fIsGNNComponent = true;
404
405 Initialize(batchSize);
406 std::string hgname;
407 if(!fIsGNNComponent) {
408 fGC.clear();
409 GenerateHeaderInfo(hgname);
410 if (fUseSession) {
411 fGC += "struct Session {\n";
412 }
413 }
414
417
418 if (fUseSession) {
419 // add here specific operator code that needs to define session data members
420 fGC += "\n";
421 for (size_t id = 0; id < fOperators.size(); id++) {
422 std::string opName = std::to_string(id);
423 fGC += fOperators[id]->GenerateSessionMembersCode(opName);
424 }
425 fGC += "\n";
426 // here add initialization and reading of weight tensors
427 if (fUseWeightFile) {
428 fGC += "Session(std::string filename =\"\") {\n";
429 fGC += " if (filename.empty()) filename = \"" + fName;
431 fGC += ".dat\";\n";
432 }
434 fGC += ".root\";\n";
435 }
437 //fUseWeightFile = fUseWeightFile;
438 } else {
439 // no need to pass weight file since it is not used
440 // keep passing a string for compatibility
441 fGC += "Session(std::string = \"\") {\n";
442 }
443
444 // add here initialization code
445 for (size_t id = 0; id < fOperators.size() ; id++) {
446 fGC += fOperators[id]->GenerateInitCode();
447 }
448
449 fGC += "}\n\n";
450 }
451
453
454 if(!fIsGNNComponent) {
455 if (fUseSession) {
456 fGC += "};\n";
457 }
458 fGC += ("} //TMVA_SOFIE_" + fName + "\n");
459 fGC += "\n#endif // " + hgname + "\n";
460 }
461}
462
464 // generate the code to read initialized tensors from a text data file
466 if (fInitializedTensors.empty()) return;
467
468 fGC += " std::ifstream f;\n";
469 fGC += " f.open(filename);\n";
470 fGC += " if (!f.is_open()) {\n";
471 fGC += " throw std::runtime_error(\"tmva-sofie failed to open file for input weights\");\n";
472 fGC += " }\n";
473
474 if(fIsGNNComponent) {
475 fGC += " f.seekg(" + std::to_string(pos) + ");\n";
476 }
477
478 fGC += " std::string tensor_name;\n";
479 fGC += " size_t length;\n";
480
481 // loop on tensors and parse the file
482 for (auto& i: fInitializedTensors) {
483 if (i.second.fType == ETensorType::FLOAT) {
484 size_t length = 1;
485 length = ConvertShapeToLength(i.second.fShape);
486 std::string tensor_name = "tensor_" + i.first;
487 std::string slength = std::to_string(length);
488 fGC += " f >> tensor_name >> length;\n";
489 fGC += " if (tensor_name != \"" + tensor_name + "\" ) {\n";
490 fGC += " std::string err_msg = \"TMVA-SOFIE failed to read the correct tensor name; expected name is " +
491 tensor_name + " , read \" + tensor_name;\n";
492 fGC += " throw std::runtime_error(err_msg);\n";
493 fGC += " }\n";
494 fGC += " if (length != " + slength + ") {\n";
495 fGC += " std::string err_msg = \"TMVA-SOFIE failed to read the correct tensor size; expected size is " +
496 slength + " , read \" + std::to_string(length) ;\n";
497 fGC += " throw std::runtime_error(err_msg);\n";
498 fGC += " }\n";
499 fGC += " for (size_t i = 0; i < length; ++i)\n";
500 fGC += " f >> " + tensor_name + "[i];\n";
501 }
502 }
503 fGC += " f.close();\n";
504 }
505
506 // generate the code to read initialized tensors from a ROOT data file
508 fGC += " {\n";
509 fGC += " std::unique_ptr<TFile> rootFile(TFile::Open(filename.c_str(), \"READ\"));\n";
510 fGC += " if (!rootFile->IsOpen()) {\n";
511 fGC += " throw std::runtime_error(\"tmva-sofie failed to open ROOT file for input weights\");\n";
512 fGC += " }\n";
513
514 std::string dirName = fName + "_weights";
515 fGC += " if (!rootFile->GetKey(\"" + dirName + "\")) {\n";
516 fGC += " throw std::runtime_error(\"tmva-sofie failed to open ROOT directory for input weights\");\n";
517 fGC += " }\n";
518
519 for (auto &i : fInitializedTensors) {
520 fGC += " {\n";
521 std::string tensor_name = "tensor_" + i.first;
522 if (i.second.fType == ETensorType::FLOAT) {
523 fGC += " fTensor_" + i.first + " = *reinterpret_cast<std::vector<float>*>(rootFile->Get(\"";
524 fGC += dirName + "/" + tensor_name + "\"));\n";
525 } else if (i.second.fType == ETensorType::DOUBLE) {
526 fGC += " fTensor_" + i.first + " = *reinterpret_cast<std::vector<double>*>(rootFile->Get(\"";
527 fGC += dirName + + "/" + tensor_name + "\"));\n";
528 } else if (i.second.fType == ETensorType::INT64) {
529 fGC += " fTensor_" + i.first + " = *reinterpret_cast<std::vector<int64_t>*>(rootFile->Get(\"";
530 fGC += dirName + "/" + tensor_name + "\"));\n";
531 }
532 fGC += " }\n";
533 }
534 fGC += " }\n";
535 }
536}
537
539 // Determine the file extension based on the weight file type
540 std::string fileExtension;
541 switch (fWeightFile) {
543 fileExtension = ".dat";
544 break;
546 fileExtension = ".root";
547 break;
549 fileExtension = ".dat";
550 break;
551 }
552
553 // If filename is empty, use the model name as the base filename
554 if (filename.empty()) {
555 filename = fFileName + fileExtension;
556 }
557
558 // Write the initialized tensors to the file
560 if(fIsGNNComponent || fIsGNN) {
561 throw std::runtime_error("SOFIE-GNN yet not supports writing to a ROOT file.");
562 }
563 std::unique_ptr<TFile> outputFile(TFile::Open(filename.c_str(), "UPDATE"));
564
565 std::string dirName = fName + "_weights";
566 // check if directory exists, in case delete to replace with new one
567 if (outputFile->GetKey(dirName.c_str()))
568 outputFile->rmdir(dirName.c_str());
569
570 auto outputDir = outputFile->mkdir(dirName.c_str());
571
572 for (const auto& item : fInitializedTensors) {
573 std::string tensorName = "tensor_" + item.first;
574 size_t length = 1;
575 length = ConvertShapeToLength(item.second.fShape);
576 if(item.second.fType == ETensorType::FLOAT) {
577 const std::shared_ptr<void> ptr = item.second.fData; // shared_ptr<void> instance
578 const float* data = (std::static_pointer_cast<float>(item.second.fData)).get();
579 std::vector<float> tensorDataVector(data, data + length);
580 outputDir->WriteObjectAny(&tensorDataVector, "std::vector<float>", tensorName.c_str());
581 }
582 else if(item.second.fType == ETensorType::DOUBLE) {
583 const std::shared_ptr<void> ptr = item.second.fData; // shared_ptr<void> instance
584 const double* data = (std::static_pointer_cast<double>(item.second.fData)).get();
585 std::vector<double> tensorDataVector(data, data + length);
586 outputDir->WriteObjectAny(&tensorDataVector, "std::vector<double>", tensorName.c_str());
587 }
588 else if(item.second.fType == ETensorType::INT64) {
589 const std::shared_ptr<void> ptr = item.second.fData; // shared_ptr<void> instance
590 const int64_t* data = (std::static_pointer_cast<int64_t>(item.second.fData)).get();
591 std::vector<int64_t> tensorDataVector(data, data + length);
592 outputDir->WriteObjectAny(&tensorDataVector, "std::vector<int64_t>", tensorName.c_str());
593 }
594 }
595 outputFile->Write(filename.c_str());
596
597 // this needs to be changed, similar to the text file
598 return -1;
599
600 } else if (fWeightFile == WeightFileType::Text) {
601 std::ofstream f;
602 if(fIsGNNComponent) {
603 // appending all GNN components into the same file
604 f.open(filename, std::ios::app);
605 } else {
606 f.open(filename);
607 }
608 if (!f.is_open())
609 throw
610 std::runtime_error("tmva-sofie failed to open file for tensor weight data");
611 for (auto& i: fInitializedTensors) {
612 if (i.second.fType == ETensorType::FLOAT) {
613 size_t length = 1;
614 for (auto &dim : i.second.fShape) {
615 length *= dim;
616 }
617 std::string tensor_name = "tensor_" + i.first;
618 f << tensor_name << " " << length << "\n";
619 const float * data = (std::static_pointer_cast<float>(i.second.fData)).get();
620 for (size_t idx = 0; idx < length - 1; idx++) {
621 f << std::setprecision(std::numeric_limits<float>::max_digits10) << data[idx] << " ";
622 }
623 f << std::setprecision(std::numeric_limits<float>::max_digits10) << data[length - 1];
624 f << "\n";
625 }
626 }
627 long curr_pos = f.tellp();
628 f.close();
629 return curr_pos;
630 } else {
631 return -1;
632 }
633}
634
636 std::cout << "Model requires following inputs:\n";
637 for (auto& inputInfo: fInputTensorInfos) {
638 std::cout << "Parameterised Tensor name: " << inputInfo.first << "\t";
639 std::cout << "type: " << ConvertTypeToString(inputInfo.second.type) << "\t";
640 std::cout << "shape: [";
641 for (size_t i = 0; i < inputInfo.second.shape.size(); i++) {
642 if (inputInfo.second.shape[i].isParam) {
643 std::cout << inputInfo.second.shape[i].param;
644 } else {
645 std::cout << inputInfo.second.shape[i].dim ;
646 }
647 if (i < inputInfo.second.shape.size() - 1) std::cout << ",";
648 }
649 std::cout << "]" << std::endl;
650 }
651
652 for (auto& inputInfo: fReadyInputTensorInfos) {
653 std::cout << "Fully Specified Tensor name: " << inputInfo.first << "\t";
654 std::cout << "type: " << ConvertTypeToString(inputInfo.second.type) << "\t";
655 std::cout << "shape: [";
656 for (size_t i = 0; i < inputInfo.second.shape.size(); i++) {
657 std::cout << inputInfo.second.shape[i];
658 if (i < inputInfo.second.shape.size() - 1) std::cout << ",";
659 }
660 std::cout << "]" << std::endl;
661 }
662
663}
664
666 std::cout << "Model initialized the following tensors:\n";
667 for (auto& it: fInitializedTensors) {
668 std::cout << "Tensor name: \"" << it.first << "\"\t";
669 std::cout << "type: " << ConvertTypeToString(it.second.fType) << "\t";
670 std::cout << "shape: [";
671 for (size_t i = 0; i < it.second.fShape.size(); i++) {
672 std::cout << it.second.fShape[i];
673 if (i < it.second.fShape.size() - 1) std::cout << ",";
674 }
675 std::cout << "]" << std::endl;
676 }
677}
678
680 std::cout << "Model specify the following intermediate tensors:\n";
681 for (auto& it: fIntermediateTensorInfos) {
682 std::cout << "Tensor name: \"" << it.first << "\"\t";
683 std::cout << "type: " << ConvertTypeToString(it.second.type) << "\t";
684 std::cout << "shape: [";
685 for (size_t i = 0; i < it.second.shape.size(); i++) {
686 std::cout << it.second.shape[i];
687 if (i < it.second.shape.size() - 1) std::cout << ",";
688 }
689 std::cout << "]" << std::endl;
690 }
691}
692
694 std::cout << "Model specify the following output tensors:\n";
695 for (auto& it: fOutputTensorNames) {
696 std::cout << "Tensor name: \"" << it << "\"\t";
697 std::cout << "shape: " << ConvertShapeToString(GetTensorShape(it)) << std::endl;
698 }
699}
700
701void RModel::HeadInitializedTensors(std::string name, int n_print) {
702 auto it = fInitializedTensors.find(name);
703 if (it == fInitializedTensors.end()) {
704 std::cout << "Tensor " << name << " not found in model's intialized tensor list" << std::endl;
705 return;
706 }
707
708 std::cout << "Tensor name: " << it->first << "\t";
709 std::cout << "type: " << ConvertTypeToString(it->second.fType) << "\t";
710 int length =1;
711 std::cout << "shape: [";
712 for (size_t i = 0; i < it->second.fShape.size(); i++) {
713 std::cout << it->second.fShape[i];
714 length *= it->second.fShape[i];
715 if (i < it->second.fShape.size() - 1) std::cout << ",";
716 }
717 std::cout << "]" << std::endl;
718 bool ellipsis = true;
719 if (n_print > length) {
720 n_print = length;
721 ellipsis = false;
722 }
723
724 std::cout << "data: [" << std::endl;
725 if (it->second.fType == ETensorType::FLOAT) {
726 auto converted_data = std::static_pointer_cast<float>(it->second.fData).get();
727 for (int i =0; i < n_print; i++) {
728 std::cout << converted_data[i];
729 if (i < n_print - 1) std::cout << " ,";
730 }
731 }
732 if (ellipsis) std::cout << ", ...";
733 std::cout << "]" << std::endl;
734
735}
736
737void RModel::OutputGenerated(std::string filename, bool append) {
738
740
741 // write weights in a text file
742 if (fUseWeightFile) {
743 if (!filename.empty()) {
744 size_t pos = filename.find(".hxx");
746 filename.replace(pos, 4, ".dat");
748 filename = filename.erase(pos, 4);
749 filename += ".root";
750 }
751 } else {
752 filename = fName;
753 filename += fWeightFile == WeightFileType::Text ? ".dat" : ".root";
754 }
756 }
757}
758
759void RModel::Streamer(TBuffer &R__b) {
760 if (R__b.IsReading()) {
761 RModel::Class()->ReadBuffer(R__b, this);
762 for(auto i=RModel::fInitializedTensors.begin(); i!=RModel::fInitializedTensors.end(); ++i) {
763 i->second.CastPersistentToShared();
764 }
765 }
766 else {
767 for(auto i=RModel::fInitializedTensors.begin(); i!=RModel::fInitializedTensors.end(); ++i) {
768 i->second.CastSharedToPersistent();
769 }
770 RModel::Class()->WriteBuffer(R__b, this);
771 }
772}
773
774}//SOFIE
775}//Experimental
776}//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 data
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 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:4075
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:737
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:701
const std::vector< size_t > & GetTensorShape(std::string name)
Definition RModel.cxx:55
long WriteInitializedTensorsToFile(std::string filename="")
Definition RModel.cxx:538
void Generate(std::underlying_type_t< Options > options, int batchSize=1, long pos=0)
Definition RModel.cxx:381
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