Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
SOFIE_common.hxx
Go to the documentation of this file.
1#ifndef TMVA_SOFIE_SOFIE_COMMON
2#define TMVA_SOFIE_SOFIE_COMMON
3
4#include "TMVA/RTensor.hxx"
5
6#include "ROOT/RSpan.hxx"
7
8#include <stdexcept>
9#include <type_traits>
10#include <cstdint>
11#include <cstring>
12#include <complex>
13#include <string>
14#include <vector>
15#include <map>
16#include <memory>
17#include <regex>
18#include <set>
19#include <sstream>
20#include <iostream>
21#include <iomanip>
22#include <cassert>
23#include <limits>
24
25namespace TMVA {
26namespace Experimental {
27namespace SOFIE {
28
29enum class ETensorType{
30 UNDEFINED = 0, FLOAT = 1, UINT8 = 2, INT8 = 3, UINT16 = 4, INT16 = 5, INT32 = 6, INT64 = 7, STRING = 8, BOOL = 9, //order sensitive
31 FLOAT16 = 10, DOUBLE = 11, UINT32 = 12, UINT64 = 13, COMPLEX64 = 14, COMPLEX28 = 15, BFLOAT16 = 16
32};
33
34enum class EActivationType{
35 UNDEFINED = 0, RELU = 1, SOFTMAX = 2, SIGMOID = 3, LEAKYRELU = 4, TANH = 5, ELU = 6
36};
37
38constexpr size_t GetTypeSize(ETensorType type) {
39 switch (type) {
40 case ETensorType::FLOAT: return sizeof(float);
41 case ETensorType::DOUBLE: return sizeof(double);
42 case ETensorType::UINT8: return sizeof(uint8_t);
43 case ETensorType::INT8: return sizeof(int8_t);
44 case ETensorType::UINT16: return sizeof(uint16_t);
45 case ETensorType::INT16: return sizeof(int16_t);
46 case ETensorType::INT32: return sizeof(int32_t);
47 case ETensorType::INT64: return sizeof(int64_t);
48 case ETensorType::UINT32: return sizeof(uint32_t);
49 case ETensorType::UINT64: return sizeof(uint64_t);
50 case ETensorType::BOOL: return sizeof(bool);
51 case ETensorType::STRING: return sizeof(std::string);
52 default: return 0;
53 }
54}
55
56typedef std::int64_t int_t;
57
60
61// find if a string represents a number
62bool IsInteger(const std::string & s);
63
64struct Dim{
65 bool isParam = false;
66 size_t dim = 0;
67 std::string param;
68
69 // default constructor (for I/O)
70 Dim() {}
71
72 // constructor for a parametric dimension with the option to pass a default dim value
73 // We use -1 for dim to indicate that the param dimension is an expression (e.g. "d1+d2")
74 // in case the string represents a number make Dim not parametric
75 Dim(const std::string & p, size_t d = 0) : isParam(true), dim(d), param(p)
76 {
77 if (IsInteger(p)) {
78 isParam = false;
79 dim = std::stoi(p);
80 }
81 }
82
83 // constructor for a non-parametric dimension
84 Dim(size_t d) : dim(d) {}
85
86 std::string GetVal() const {
87 // cast to int64_t for negative shape values
88 return (isParam) ? param : std::to_string(static_cast<int64_t>(dim));
89 }
90
91 std::ostream& operator<< (std::ostream& os) const {
92 os << GetVal();
93 return os;
94 }
95
96 bool operator==(const Dim& rhs) const {
97 return (isParam && rhs.isParam) ? param == rhs.param : dim == rhs.dim;
98 }
99 bool operator!=(const Dim& rhs) const {
100 return !(*this == rhs);
101 }
102};
103
104//bool operator==(const Dim& lhs, const Dim& rhs);
105inline std::ostream & operator<< (std::ostream &os, const Dim &d) {
106 os << d.GetVal();
107 return os;
108}
109
112 std::vector<Dim> shape;
113};
114
117 std::vector<size_t> shape;
118};
119
122 std::vector<Dim> shape;
123};
124
125// template traits for Tensor Shape
126template <typename T>
127struct TensorShape {};
128template<>
130 static bool IsDim() { return true; }
131};
132template<>
133struct TensorShape<size_t> {
134 static bool IsDim() { return false; }
135};
136
137// template traits for Tensor type
138template <typename T>
139struct TensorType {};
140template<>
141struct TensorType<float> {
142 static const std::string Name() { return "float"; }
143};
144template<>
146 static const std::string Name() { return "double"; }
147};
148template<>
149struct TensorType<int64_t> {
150 static const std::string Name() { return "int64_t"; }
151};
152template<>
153struct TensorType<int32_t> {
154 static const std::string Name() { return "int32_t"; }
155};
156template<>
157struct TensorType<uint32_t> {
158 static const std::string Name() { return "uint32_t"; }
159};
160template<>
161struct TensorType<uint64_t> {
162 static const std::string Name() { return "uint64_t"; }
163};
164template<>
166 static const std::string Name() { return "bool"; }
167};
168template<>
169struct TensorType<int8_t> {
170 static const std::string Name() { return "int8_t"; }
171};
172template<>
173struct TensorType<uint8_t> {
174 static const std::string Name() { return "uint8_t"; }
175};
176
178 std::string_view tensor_name;
180
181 TensorMemoryInfo split(const std::string_view new_name, size_t new_size) {
182 if (new_size > tensor_size) {
183 throw std::invalid_argument("New size exceeds available tensor size.");
184 }
187 }
188
189 // Method to merge another struct into this one
191 tensor_size += other.tensor_size;
192 }
193};
194
196
197 // ordered map with chunk_idx as key and TensorMemoryInfo as value
198 std::map<size_t, TensorMemoryInfo> total_stack;
199
200 // ordered map with chunk_idx as key and chunk_size as value
201 std::map<size_t, size_t> available_stack;
202};
203
204std::vector<Dim> ConvertShapeToDim(const std::vector<size_t> & shape);
205
206std::vector<size_t> ConvertShapeToInt(const std::vector<Dim> & shape);
207
208std::size_t ConvertShapeToLength(const std::vector<size_t> & shape);
209
210std::string ConvertShapeToString(const std::vector<size_t> & shape);
211std::string ConvertDimShapeToString(const std::vector<Dim> & shape);
212
213std::string ConvertDimShapeToLength(const std::vector<Dim> & shape);
214
215
216template<class T>
217std::string ConvertValToString(T value) {
218 std::stringstream ret;
219 ret << std::to_string(value);
220 return ret.str();
221}
222// float specialization
223template<>
224inline std::string ConvertValToString<float>(float value) {
225 std::stringstream ret;
226 // special case for infinity and Nan
227 if (std::isinf(value))
228 ret << (value > 0 ? "std::numeric_limits<float>::infinity()" :
229 "-std::numeric_limits<float>::infinity()");
230 else if (std::isnan(value))
231 ret << "std::numeric_limits<float>::quiet_NaN()";
232 else {
233 ret << std::setprecision(std::numeric_limits<float>::max_digits10);
234 ret << value;
235 }
236 return ret.str();
237}
238// double specialization
239template<>
240inline std::string ConvertValToString<double>(double value) {
241 std::stringstream ret;
242 // special case for infinity and Nan
243 if (std::isinf(value))
244 ret << (value > 0 ? "std::numeric_limits<double>::infinity()" :
245 "-std::numeric_limits<double>::infinity()");
246 else if (std::isnan(value))
247 ret << "std::numeric_limits<double>::quiet_NaN()";
248 else {
249 ret << std::setprecision(std::numeric_limits<double>::max_digits10);
250 ret << value;
251 }
252 return ret.str();
253}
254// int64_t specialization for INT64_MIN
255template<>
256inline std::string ConvertValToString<int64_t>(int64_t value) {
257 std::stringstream ret;
258 if (value == INT64_MIN)
259 ret << "INT64_MIN";
260 else
261 ret << std::to_string(value);
262 return ret.str();
263}
264
265
266// convert list of values in a string taking into account the precision
267template<class T>
268std::string ConvertValuesToString(size_t n, const T * data, size_t maxprint = -1) {
269 std::stringstream ret;
270 ret << "{ ";
271 for (size_t i = 0; i < std::min(n,maxprint); i++) {
273 if (i < n-1) ret << ", ";
274 if (i < n-1 && i == maxprint-1) ret << "..... ";
275 }
276 ret << "}";
277 return ret.str();
278}
279template<class T>
280std::string ConvertValuesToString(const std::vector<T> & data, size_t maxprint = 5) {
281 return ConvertValuesToString(data.size(), data.data(), maxprint);
282}
283
285public:
286 InitializedTensor() = default;
287 InitializedTensor(ETensorType type, std::span<std::size_t> shape, std::shared_ptr<void> data, bool typeConstant = false)
288 : fConstant(typeConstant), fType{type}, fShape{shape.begin(), shape.end()}, fData{data}
289 {
290 }
291
292 ETensorType const &type() const { return fType; }
293 std::vector<std::size_t> const &shape() const { return fShape; }
294 std::shared_ptr<void> const &sharedptr() const { return fData; }
295 // query if tensor comes from a Constant operator
296 bool IsConstantTensor() const { return fConstant;}
297 // query if tensor needs to be written in a weight file. Constant tensors are not written in a separate file
298 bool IsWeightTensor() const { return !fConstant && !fIsNotWritable;}
299 // check if a Tensor is Writable (need to be written in the file or in the generated code (e.g. as a constant tensor)
300 // if an initialized tensors is used in a constant operator at compile time does not need to be written and can be omitted in
301 // the generated code
302 bool IsNotWritable() const { return fIsNotWritable; }
303 // set not writable initialized tensors - i.e. tensor that must not be written in a file
305 // set writable initialized tensors - i.e. tensor that must be written in a file
306 void SetWritable() { fIsNotWritable = false;}
307 // set as constant (needed for non-float initialized tensors)
308 void SetConstant() { fConstant = true;}
309
310 template <class T = void>
311 T const *data() const
312 {
313 return static_cast<T const *>(fData.get());
314 }
315
316private:
317 bool fConstant = false; ///< Flag specifying if tensor is a Constant one (coming from a Constant operator)
318 bool fIsNotWritable = false; ///< Flag to indicate that tensor values do not need to be written as weight or generated code
319 ETensorType fType; ///< Encodes the type of the data
320 std::vector<std::size_t> fShape; ///< The shape of the data in terms of elements in each dimension
321 std::shared_ptr<void> fData; ///<! Transient shared data
322};
323
324template <typename T>
326 if (std::is_same<T, float>::value) return ETensorType::FLOAT;
327 if (std::is_same<T, uint8_t>::value) return ETensorType::UINT8;
328 if (std::is_same<T, int8_t>::value) return ETensorType::INT8;
329 if (std::is_same<T, uint16_t>::value) return ETensorType::UINT16;
330 if (std::is_same<T, int16_t>::value) return ETensorType::INT16;
331 if (std::is_same<T, int32_t>::value) return ETensorType::INT32;
332 if (std::is_same<T, int64_t>::value) return ETensorType::INT64;
333 if (std::is_same<T, std::string>::value) return ETensorType::STRING;
334 if (std::is_same<T, bool>::value) return ETensorType::BOOL;
335 //float16 unimplemented
336 if (std::is_same<T, double>::value) return ETensorType::DOUBLE;
337 if (std::is_same<T, uint32_t>::value) return ETensorType::UINT32;
338 if (std::is_same<T, uint64_t>::value) return ETensorType::UINT64;
339 //complex 64, 28, bfloat 16 unimplemented
340}
341
342namespace UTILITY{
343
344
345
346// clean operator and tensor names
347std::string Clean_name(std::string input_tensor_name);
348
349// Check if two shapes are equal
350bool AreSameShape(const std::vector<size_t>&, const std::vector<size_t>&);
351bool AreSameShape(const std::vector<size_t>&, const std::vector<Dim>&);
352bool AreSameShape(const std::vector<Dim>&, const std::vector<Dim>&);
353
354
355// Multidirectional broadcast a list of tensors to the same shape
356std::vector<size_t> MultidirectionalBroadcastShape(std::vector<std::vector<size_t>>);
357
358// Multidirectional broadcast two shapes to the same shape
359
360std::pair<int, std::vector<size_t>> MultidirectionalBroadcastShape(std::vector<size_t> &, std::vector<size_t> &);
361std::vector<size_t> UnidirectionalBroadcastShape(std::vector<size_t> &, std::vector<size_t> &);
362
363std::pair<int, std::vector<Dim>> MultidirectionalBroadcastShape(std::vector<Dim> &, std::vector<Dim> &);
364
365
366
367template<typename T>
368T* BroadcastConvBias(const T* data, const size_t channel, const std::vector<size_t>& targetShape) {
369 size_t size = targetShape.size();
370 if (targetShape[1] != channel) {
371 std::stringstream ss;
372 ss << "TMVA::SOFIE - Error broadcasting Conv Bias of shape {";
373 ss << std::to_string(channel);
374 ss << "} to ";
376 throw
377 std::runtime_error(ss.str());
378 }
379
381 T* newData = new T[targetLength];
382
383 if (targetLength == channel) {
384 std::copy(data, data + channel, newData);
385 return newData;
386 }
387
388 // cStride = OutDepth * outHeight * outWidth
389 size_t cStride = 1;
390 for (size_t i = 2; i < size; i++)
391 cStride *= targetShape[i];
392 // Broadcast each element of the bias to a vector of size cStride and concatenate them
393 // into a vector of size channel * cStride
394 for (size_t i = 0; i < channel; i++) {
395 std::fill(newData + i * cStride, newData + (i + 1) * cStride, data[i]);
396 }
397 // Broadcast newData[0...channel * cStride) to newData[0...batch * channel * cStride)
398 size_t batch = targetShape[0];
399 size_t bStride = channel * cStride;
400 for (size_t i = 1; i < batch; i++) {
401 std::copy(newData, newData + bStride, newData + i * bStride);
402 }
403 return newData;
404}
405
406// Broadcast a tensor from shape to targetShape according to numpy broadcasting rules
407// See more at https://numpy.org/doc/stable/user/basics.broadcasting.html
408// and https://github.com/onnx/onnx/blob/main/docs/Broadcasting.md .
409template<typename T, class ConstContT = std::span<const T>>
410void BroadcastTensor(ConstContT data, const std::vector<size_t>& shape, const std::vector<size_t>& targetShape, T *broadcastedData) {
411 // Size of the shapes (tensor input here have shapes with same sizes, we have already added the needed ones )
412 size_t size = shape.size();
413 // Current length of the broadcasted tensor
414 size_t curLength = data.size();
415 // special case when broadcasting last dimensions (initial shapes must be the same)
416 if (size > 1 && shape.front() == targetShape.front() && shape.back() == 1) {
417 size_t bsize = targetShape.back();
418 // compute the size of the data to broadcast
419 for (int k = int(size)-2; k >=0; k--) {
420 if (shape[k] != 1) break;
421 bsize *= targetShape[k];
422 }
423 for (size_t i = 0; i < curLength; i++) {
424 std::fill(broadcastedData + i*bsize, broadcastedData + (i+1)*bsize , data[i]);
425 }
426 return;
427 }
428
429 std::copy(data.begin(), data.end(), broadcastedData);
430 // Product of the previous dimensions of targetShape
431 size_t arrayNum = 1;
432 // New broadcasted data: is this needed?
434
435 for (size_t idx = 0; idx < size; idx++) {
436 size_t dim = shape[idx];
437 size_t targetDim = targetShape[idx];
438 if (dim == 1 && targetDim > 1) {
439 // Set the new length of the data
440 size_t newLength = curLength * targetDim;
441 // View the data as a list of arrayNum arrays of size arrayLength
442 size_t arrayLength = curLength / arrayNum;
443 // Broadcast each array dim times
444 if (arrayLength > 1) {
445 // If each array has at least two elements
446 for (size_t arrayIdx = 0; arrayIdx < arrayNum; arrayIdx++) {
447 for (size_t targetIdx = 0; targetIdx < targetDim; targetIdx++) {
451 newData.begin() + offset);
452 }
453 }
454 } else {
455 // If each array has one element
456 for (size_t arrayIdx = 0; arrayIdx < arrayNum; arrayIdx++) {
457 std::fill(newData.begin() + arrayIdx * targetDim,
459 }
460 }
461 // Update current length
463 // Update broadcasted data
465 }
466 // Update the number of arrays
468 }
469}
470
471// interface where we allocate a new array for broadcasted data
472template<typename T>
473T* CreateBroadcastTensor(const T* data, const std::vector<size_t>& shape, const std::vector<size_t>& targetShape, size_t targetLength) {
474 // newShape is an array of size equal to dimension along which we are broadcasting the tensor
475 T* broadcastedData = new T[targetLength];
476 size_t curLength = ConvertShapeToLength(shape);
478 return broadcastedData;
479}
480// Unidirectional broadcasting shape to targetShape// In unidirectional broadcast - only tensor B can have the shape changed not
481// tensor A - otherwise is a multidirectional broadcast
482template<typename T>
483T* UnidirectionalBroadcast(const T* data, const std::vector<size_t>& shape, const std::vector<size_t>& targetShape) {
484 // Prepend shape with ones
485 if (shape.size() < targetShape.size()) {
486 size_t targetSize = targetShape.size();
487 std::vector<size_t> newShape(targetSize, 1);
488 size_t offset = targetSize - shape.size();
489 std::copy(shape.begin(), shape.end(), newShape.begin() + offset);
491 }
493}
494
495// Unidirectional broadcasting shape to targetShape using a passed vector to avoid allocations
496template<typename T>
497void UnidirectionalBroadcast(const T* data, const std::vector<size_t>& shape, const std::vector<size_t>& targetShape, T *broadcastedData) {
498 size_t curLength = ConvertShapeToLength(shape);
499 std::span<T> inData(const_cast<T*>(data), curLength);
500 // Prepend shape with ones
501 if (shape.size() < targetShape.size()) {
502 size_t targetSize = targetShape.size();
503 std::vector<size_t> newShape(targetSize, 1);
504 size_t offset = targetSize - shape.size();
505 std::copy(shape.begin(), shape.end(), newShape.begin() + offset);
507 return;
508 }
510}
511
512/// compute stride of a tensor given its shape (assume layout is row-major)
513std::vector<size_t> ComputeStrideFromShape(const std::vector<size_t> & shape);
514std::vector<Dim> ComputeStrideFromShape(const std::vector<Dim> & shape);
515
516
517} // end namespace UTILITY
518
519namespace BLAS{
520extern "C" void sgemm_(const char * transa, const char * transb, const int * m, const int * n, const int * k,
521 const float * alpha, const float * A, const int * lda, const float * B, const int * ldb,
522 const float * beta, float * C, const int * ldc);
523}//BLAS
524
525
526struct GNN_Data {
527 RTensor<float> node_data; // the node feature data, tensor with shape (num_nodes, num_node_features)
528 RTensor<float> edge_data; // the edge feature data, tensor with shape (num_edges, num_edge_features)
529 RTensor<float> global_data; // the global features, tensor with shape (1, num_global_features)
530 RTensor<int> edge_index; // the edge index (receivers and senders for each edge), tensor with shape (2, num_edges)
531 // edge_index[0,:] are the receivers and edge_index[1,:] are the senders
532
533
534 // need to have default constructor since RTensor has not one
536
537};
538
539template<typename T>
541{
542 // concatenate tensor along axis. Shape must be the same except in the dimension of the concatenated axis
543 if (t1.GetMemoryLayout() != t2.GetMemoryLayout())
544 throw std::runtime_error("TMVA RTensor Concatenate - tensors have different memory layout");
545 auto & shape1 = t1.GetShape();
546 auto & shape2 = t2.GetShape();
547 if (t1.GetSize()/shape1[axis] != t2.GetSize()/shape2[axis]) {
548 std::cout << "axis " << axis << " sizes " << t1.GetSize() << " " << t2.GetSize() << " ";
549 std::cout << "shape 1 : " << ConvertShapeToString(t1.GetShape());
550 std::cout << " shape 2 : " << ConvertShapeToString(t2.GetShape()) << std::endl;
551 throw std::runtime_error("TMVA RTensor Concatenate - tensors have incompatible shapes");
552 }
553 std::vector<size_t> outShape = shape1;
554 outShape[axis] = shape1[axis] + shape2[axis];
556 if (t1.GetMemoryLayout() == TMVA::Experimental::MemoryLayout::ColumnMajor) {
557 throw std::runtime_error("TMVA RTensor Concatenate is not yet supported for column major tensors");
558 }
559
560 auto & stride1 = t1.GetStrides();
561 auto & stride2 = t2.GetStrides();
562 auto & outStride = tout.GetStrides();
563
564 size_t s1 = (axis > 0) ? stride1[axis-1] : t1.GetSize(); // block size to copy from first tensor
565 size_t s2 = (axis > 0) ? stride2[axis-1] : t2.GetSize(); // block size to copy from second tensor
566 size_t sout = (axis > 0) ? outStride[axis-1] : tout.GetSize();
567 size_t nb = t1.GetSize()/s1;
568 for (size_t i = 0; i < nb; i++) {
569 std::copy(t1.GetData() + i*s1, t1.GetData() + (i+1)*s1, tout.GetData() + i * sout );
570 std::copy(t2.GetData() + i*s2, t2.GetData() + (i+1)*s2, tout.GetData() + i * sout + s1 );
571 }
572
573 return tout;
574}
575
576
577inline GNN_Data Concatenate(GNN_Data & data1, GNN_Data & data2, int axis = 0) {
578 GNN_Data out;
579 out.node_data = Concatenate(data1.node_data,data2.node_data, axis);
580 out.edge_data = Concatenate(data1.edge_data,data2.edge_data, axis);
581 out.global_data = Concatenate<float>(data1.global_data,data2.global_data, axis-1);
582 // assume sender/receivers of data1 and data2 are the same
583 out.edge_index = data1.edge_index.Copy();
584 return out;
585}
586
587inline GNN_Data Copy(const GNN_Data & data) {
588 GNN_Data out;
589 out.node_data = RTensor<float>(data.node_data.GetShape());
590 out.edge_data = RTensor<float>(data.edge_data.GetShape());
591 out.global_data = RTensor<float>(data.global_data.GetShape());
592 out.edge_index = RTensor<int>(data.edge_index.GetShape());
593 std::copy(data.node_data.GetData(), data.node_data.GetData()+ data.node_data.GetSize(), out.node_data.GetData());
594 std::copy(data.edge_data.GetData(), data.edge_data.GetData()+ data.edge_data.GetSize(), out.edge_data.GetData());
595 std::copy(data.global_data.GetData(), data.global_data.GetData()+ data.global_data.GetSize(), out.global_data.GetData());
596 std::copy(data.edge_index.GetData(), data.edge_index.GetData()+ data.edge_index.GetSize(), out.edge_index.GetData());
597 return out;
598}
599
600
601//Utility functions to generate code
602void EmitNestedLoops(std::stringstream &out, size_t loopRank, const std::vector<Dim> shape);
603void CloseNestedLoops(std::stringstream &out, size_t loopRank);
604
605
606
607/// Source code of the inference helper functions to embed in generated code so
608/// that it is standalone and does not need to include TMVA/SOFIE_common.hxx.
610 std::string includes; ///< #include directives to place in the header preamble
611 std::string definitions; ///< function/type definitions to place inside the generated model namespace
612 std::string cladDefinitions; ///< Clad custom-derivative definitions to place at file scope (outside the model
613 ///< namespace) so that Clad discovers them; empty when none are needed
614};
615
616/// Return the standalone C++ source of the inference helper functions requested
617/// in `neededHelpers` (see RModel_Base::AddNeededHelperFunction), resolving
618/// their inter-dependencies. Recognised keys are: "Im2col", "Im2col_3d",
619/// "col2im", "UnidirectionalBroadcast", "BroadcastConvBias", "Gemm_Call",
620/// "Relu", "Fill", "Copy", "ReadTensorFromStream", "InputTensorDims",
621/// "DynamicMemory" and "GNN_Data".
622///
623/// `modelNamespace` (e.g. "TMVA_SOFIE_MyModel") is the generated model namespace;
624/// the Clad pullbacks are emitted into clad::custom_derivatives::<modelNamespace>
625/// so the model stays differentiable without SOFIE_common.hxx / CladDerivator.h.
626///
627/// `sgemmAlreadyDeclared`: set true if the caller already emitted the `extern "C"`
628/// sgemm_ declaration (fNeededBlasRoutines block), so Gemm_Call skips its own and
629/// avoids a duplicate. Default false emits it, keeping the returned code self-contained.
631 const std::string & modelNamespace,
632 bool sgemmAlreadyDeclared = false);
633
634
635} // namespace SOFIE
636} // namespace Experimental
637} // namespace TMVA
638
639#endif //TMVA_SOFIE_COMMON
#define d(i)
Definition RSha256.hxx:102
#define s1(x)
Definition RSha256.hxx:91
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
winID h TVirtualViewer3D TVirtualGLPainter p
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 offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
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
const_iterator begin() const
RTensor is a container with contiguous memory and shape information.
Definition RTensor.hxx:163
std::shared_ptr< void > const & sharedptr() const
std::shared_ptr< void > fData
! Transient shared data
ETensorType fType
Encodes the type of the data.
std::vector< std::size_t > const & shape() const
std::vector< std::size_t > fShape
The shape of the data in terms of elements in each dimension.
bool fIsNotWritable
Flag to indicate that tensor values do not need to be written as weight or generated code.
bool fConstant
Flag specifying if tensor is a Constant one (coming from a Constant operator)
InitializedTensor(ETensorType type, std::span< std::size_t > shape, std::shared_ptr< void > data, bool typeConstant=false)
const Int_t n
Definition legend1.C:16
void sgemm_(const char *transa, const char *transb, const int *m, const int *n, const int *k, const float *alpha, const float *A, const int *lda, const float *B, const int *ldb, const float *beta, float *C, const int *ldc)
bool AreSameShape(const std::vector< size_t > &, const std::vector< size_t > &)
T * BroadcastConvBias(const T *data, const size_t channel, const std::vector< size_t > &targetShape)
std::vector< size_t > UnidirectionalBroadcastShape(std::vector< size_t > &, std::vector< size_t > &)
void BroadcastTensor(ConstContT data, const std::vector< size_t > &shape, const std::vector< size_t > &targetShape, T *broadcastedData)
std::string Clean_name(std::string input_tensor_name)
std::vector< size_t > MultidirectionalBroadcastShape(std::vector< std::vector< size_t > >)
T * UnidirectionalBroadcast(const T *data, const std::vector< size_t > &shape, const std::vector< size_t > &targetShape)
T * CreateBroadcastTensor(const T *data, const std::vector< size_t > &shape, const std::vector< size_t > &targetShape, size_t targetLength)
std::vector< size_t > ComputeStrideFromShape(const std::vector< size_t > &shape)
compute stride of a tensor given its shape (assume layout is row-major)
std::string ConvertDimShapeToString(const std::vector< Dim > &shape)
std::size_t ConvertShapeToLength(const std::vector< size_t > &shape)
std::string ConvertValToString< double >(double value)
std::string ConvertValuesToString(size_t n, const T *data, size_t maxprint=-1)
std::vector< Dim > ConvertShapeToDim(const std::vector< size_t > &shape)
Convert shape from integer format to dynamic one (based on Dim)
constexpr size_t GetTypeSize(ETensorType type)
ETensorType GetTemplatedType(T)
std::string ConvertValToString< float >(float value)
std::vector< size_t > ConvertShapeToInt(const std::vector< Dim > &shape)
Convert shape based on Dim to integer format.
std::string ConvertTypeToString(ETensorType type)
ETensorType ConvertStringToType(std::string type)
TMVA::Experimental::RTensor< T > Concatenate(TMVA::Experimental::RTensor< T > &t1, TMVA::Experimental::RTensor< T > &t2, int axis=0)
HelperFunctionsCode GenerateHelperFunctionsCode(const std::set< std::string > &neededHelpers, const std::string &modelNamespace, bool sgemmAlreadyDeclared=false)
Return the standalone C++ source of the inference helper functions requested in neededHelpers (see RM...
std::ostream & operator<<(std::ostream &os, const Dim &d)
std::string ConvertDimShapeToLength(const std::vector< Dim > &shape)
void EmitNestedLoops(std::stringstream &out, size_t loopRank, const std::vector< Dim > shape)
std::string ConvertShapeToString(const std::vector< size_t > &shape)
void CloseNestedLoops(std::stringstream &out, size_t loopRank)
std::string ConvertValToString(T value)
std::string ConvertValToString< int64_t >(int64_t value)
bool IsInteger(const std::string &s)
GNN_Data Copy(const GNN_Data &data)
create variable transformations
bool operator!=(const Dim &rhs) const
bool operator==(const Dim &rhs) const
Dim(const std::string &p, size_t d=0)
std::ostream & operator<<(std::ostream &os) const
Source code of the inference helper functions to embed in generated code so that it is standalone and...
std::string definitions
function/type definitions to place inside the generated model namespace
std::string cladDefinitions
Clad custom-derivative definitions to place at file scope (outside the model namespace) so that Clad ...
std::string includes
#include directives to place in the header preamble
std::map< size_t, TensorMemoryInfo > total_stack
std::map< size_t, size_t > available_stack
void merge(const TensorMemoryInfo &other)
TensorMemoryInfo split(const std::string_view new_name, size_t new_size)
TMarker m
Definition textangle.C:8
auto * t1
Definition textangle.C:20