NVIDIA DeepStream SDK API Reference

9.2 Release
sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #ifndef TENSOR_H
19 #define TENSOR_H
20 
21 #include <iostream>
22 #include <iomanip>
23 #include <sstream>
24 #include <fstream>
25 #include <string.h>
26 #include <cuda.h>
27 #include <cuda_runtime.h>
28 #include <vector>
29 #include "nvdsmeta.h"
30 #include <torch/torch.h>
31 #include <unordered_map>
32 
40 struct Tensor {
41  std::string name; // Name of the tensor
42  void* buffer; // Pointer to the tensor data
43  size_t size; // Size of the buffer in bytes
44  std::vector<int> shape; // Shape of the tensor (dimensions)
45  NvDsDataType data_type; // Data type of the tensor
46  int gpu_id; // GPU ID where tensor is allocated (-1 for CPU)
47  int frame_num; // Frame number associated with this tensor
48 
52  Tensor() : buffer(nullptr), size(0), shape(), data_type(NvDsDataType_FP32), gpu_id(-1), frame_num(0) {}
53 
63  inline torch::Tensor to_torch_tensor() const {
64  if (!buffer) {
65  // Return an empty tensor if buffer is invalid
66  return torch::Tensor();
67  }
68 
69  std::vector<int64_t> torch_shape;
70  torch_shape.reserve(shape.size());
71  for (auto dim : shape) {
72  torch_shape.push_back(static_cast<int64_t>(dim));
73  }
74 
75  // Create torch tensor options with appropriate device
76  auto options = torch::TensorOptions().device(gpu_id >= 0 ?
77  torch::Device(torch::kCUDA, gpu_id) : torch::Device(torch::kCPU));
78 
79  // Create torch tensor based on data type
80  switch (data_type) {
81  case NvDsDataType_FP32: {
82  float* data_ptr = static_cast<float*>(buffer);
83  return torch::from_blob(data_ptr, torch_shape, torch::kFloat32).to(options.device());
84  }
85  case NvDsDataType_INT32: {
86  int32_t* data_ptr = static_cast<int32_t*>(buffer);
87  return torch::from_blob(data_ptr, torch_shape, torch::kInt32).to(options.device());
88  }
89  case NvDsDataType_INT8: {
90  int8_t* data_ptr = static_cast<int8_t*>(buffer);
91  return torch::from_blob(data_ptr, torch_shape, torch::kInt8).to(options.device());
92  }
93  case NvDsDataType_UINT8: {
94  uint8_t* data_ptr = static_cast<uint8_t*>(buffer);
95  return torch::from_blob(data_ptr, torch_shape, torch::kUInt8).to(options.device());
96  }
97  case NvDsDataType_INT64: {
98  int64_t* data_ptr = static_cast<int64_t*>(buffer);
99  return torch::from_blob(data_ptr, torch_shape, torch::kInt64).to(options.device());
100  }
101  case NvDsDataType_UINT32: {
102  uint32_t* data_ptr = static_cast<uint32_t*>(buffer);
103  return torch::from_blob(data_ptr, torch_shape, torch::kInt32).to(options.device());
104  }
105  case NvDsDataType_UINT64: {
106  uint64_t* data_ptr = static_cast<uint64_t*>(buffer);
107  return torch::from_blob(data_ptr, torch_shape, torch::kInt64).to(options.device());
108  }
109  case NvDsDataType_FP16: {
110  uint16_t* data_ptr = static_cast<uint16_t*>(buffer);
111  return torch::from_blob(data_ptr, torch_shape, torch::kHalf).to(options.device());
112  }
113  default: {
114  // For unsupported types, return empty tensor
115  std::cerr << "Unsupported data type for conversion to torch::Tensor" << std::endl;
116  return torch::Tensor();
117  }
118  }
119  }
120 
130  inline bool release() {
131  bool memory_freed = false;
132 
133  // Check if buffer exists
134  if (buffer) {
135  // Determine if memory is on GPU or CPU based on gpu_id
136  if (gpu_id >= 0) {
137  // GPU memory - use cudaFree
138  cudaError_t err = cudaFree(buffer);
139  memory_freed = (err == cudaSuccess);
140  if (err != cudaSuccess) {
141  std::cerr << "Error freeing GPU memory: " << cudaGetErrorString(err) << std::endl;
142  }
143  } else {
144  // CPU memory - use free
145  free(buffer);
146  memory_freed = true;
147  }
148  buffer = nullptr;
149  }
150 
151  // Reset all members to initial state
152  size = 0;
153  shape.clear();
155  name.clear();
156  gpu_id = -1;
157  frame_num = 0;
158 
159  return memory_freed;
160  }
161 
167  inline ~Tensor() noexcept {
168  release();
169  }
170 
174  inline void display(bool print_data = false) const {
175  bool is_gpu_tensor = (gpu_id >= 0);
176  size_t total_elements = 1;
177  size_t max_elements = 100;
178  int precision = 4;
179  const int lineWidth = 100; // Total width inside the table
180  const std::string headerBorder = "+" + std::string(lineWidth+1, '-') + "+";
181 
182  std::cout << "\n" << headerBorder << std::endl;
183 
184  // Create header with tensor name
185  std::string tensorName = !name.empty() ? name : "Unnamed";
186  std::string headerText = "Tensor Information - " + tensorName;
187 
188  // Center the header text
189  int padding = (lineWidth - headerText.length()) / 2;
190  std::cout << "| " << std::string(padding, ' ') << headerText
191  << std::string(lineWidth - padding - headerText.length(), ' ') << "|" << std::endl;
192 
193  std::cout << headerBorder << std::endl;
194 
195  // Fixed width for label and value columns to ensure proper alignment
196  const int labelWidth = 16;
197  const int valueWidth = lineWidth - labelWidth - 3; // -3 for "| " and " |"
198 
199  // Display shape information
200  std::string shapeStr = "[";
201  if (shape.empty()) {
202  if (shape.size() > 0) {
203  shapeStr += std::to_string(shape[shape.size() - 1]);
204  } else {
205  shapeStr += "Unknown";
206  }
207  } else {
208  for (size_t i = 0; i < shape.size(); i++) {
209  shapeStr += std::to_string(shape[i]);
210  if (i < shape.size() - 1) shapeStr += ", ";
211  }
212  }
213  shapeStr += "]";
214 
215  std::string deviceStr = (is_gpu_tensor) ? "GPU [" + std::to_string(gpu_id) + "]" : "CPU";
216  std::string typeStr;
217  switch (data_type) {
218  case NvDsDataType_FP32: typeStr = "Float32"; total_elements = size / sizeof(float); break;
219  case NvDsDataType_FP16: typeStr = "Float16"; total_elements = size / sizeof(float); break;
220  case NvDsDataType_INT8: typeStr = "Int8"; total_elements = size; break;
221  case NvDsDataType_INT32: typeStr = "Int32"; total_elements = size / sizeof(int32_t); break;
222  case NvDsDataType_UINT8: typeStr = "UInt8"; total_elements = size; break;
223  case NvDsDataType_UINT32: typeStr = "UInt32"; total_elements = size / sizeof(uint32_t); break;
224  case NvDsDataType_INT64: typeStr = "Int64"; total_elements = size / sizeof(int64_t); break;
225  case NvDsDataType_UINT64: typeStr = "UInt64"; total_elements = size / sizeof(uint64_t); break;
226  default: typeStr = "Unknown"; break;
227  }
228  size_t elements_to_display = std::min(total_elements, max_elements);
229 
230  // Display all information with consistent formatting
231  std::cout << "| Shape | " << std::left << std::setw(valueWidth) << shapeStr << " |" << std::endl;
232  std::cout << "| Device | " << std::left << std::setw(valueWidth) << deviceStr << " |" << std::endl;
233  std::cout << "| Buffer Size | " << std::left << std::setw(valueWidth) << std::to_string(size) + " bytes" << " |" << std::endl;
234  std::cout << "| Elements | " << std::left << std::setw(valueWidth) << std::to_string(total_elements) << " |" << std::endl;
235  std::cout << "| Data Type | " << std::left << std::setw(valueWidth) << typeStr << " |" << std::endl;
236  if (buffer) {
237  std::cout << "| Buffer Pointer | " << std::left << std::setw(valueWidth) << buffer << " |" << std::endl;
238  } else {
239  std::cout << "| Buffer Pointer | " << std::left << std::setw(valueWidth) << "NULL" << " |" << std::endl;
240  }
241 
242  if (frame_num > 0) {
243  std::cout << "| Frame Number | " << std::left << std::setw(valueWidth) << frame_num << " |" << std::endl;
244  }
245 
246  if (print_data) {
247  // Check if buffer is null before trying to print data
248  if (!buffer) {
249  std::cout << "|" << std::string(lineWidth+1, '-') << "|" << std::endl;
250  std::cout << "| No data to display - buffer is null" << std::string(lineWidth - 34, ' ') << "|" << std::endl;
251  std::cout << headerBorder << std::endl;
252  return;
253  }
254 
255  // Divider before data section
256  std::cout << "|" << std::string(lineWidth+1, '-') << "|" << std::endl;
257  void* host_buffer = nullptr;
258  if (is_gpu_tensor) {
259  std::cout << "| Values [GPU --> CPU]:" << std::string(lineWidth - 21, ' ') << "|" << std::endl;
260  // Allocate CPU memory
261  host_buffer = malloc(size);
262  if (!host_buffer) {
263  std::cerr << "| ERROR: Failed to allocate CPU memory for tensor display"
264  << std::string(lineWidth - 51, ' ') << "|" << std::endl;
265  std::cout << headerBorder << std::endl;
266  return;
267  }
268  // Copy data from GPU to CPU
269  cudaError_t err = cudaMemcpy(host_buffer, buffer, size, cudaMemcpyDeviceToHost);
270  if (err != cudaSuccess) {
271  std::cerr << "| ERROR: Failed to copy tensor data from GPU to CPU: " << cudaGetErrorString(err)
272  << std::string(lineWidth - 59 - strlen(cudaGetErrorString(err)), ' ') << "|" << std::endl;
273  free(host_buffer);
274  std::cout << headerBorder << std::endl;
275  return;
276  }
277  } else {
278  // Data is already on CPU
279  std::cout << "| Values [CPU]:" << std::string(lineWidth - 13, ' ') << "|" << std::endl;
280  host_buffer = buffer;
281  }
282 
283  // Set floating point precision for display
284  std::cout << std::fixed << std::setprecision(precision);
285 
286  // Print data type
287  std::string typeStr;
288  switch (data_type) {
289  case NvDsDataType_FP32: typeStr = "Float32"; break;
290  case NvDsDataType_FP16: typeStr = "Float16"; break;
291  case NvDsDataType_INT8: typeStr = "Int8"; break;
292  case NvDsDataType_INT32: typeStr = "Int32"; break;
293  case NvDsDataType_UINT8: typeStr = "UInt8"; break;
294  case NvDsDataType_UINT32: typeStr = "UInt32"; break;
295  case NvDsDataType_INT64: typeStr = "Int64"; break;
296  case NvDsDataType_UINT64: typeStr = "UInt64"; break;
297  default: typeStr = "Unknown"; break;
298  }
299 
300  // Add one blank line before values
301  std::cout << "|" << std::string(lineWidth+1, ' ') << "|" << std::endl;
302 
303  const int indent = 2; // Indent from the left border
304  const int valueWidth = lineWidth - 3; // Maximum width for values per line
305  std::stringstream line;
306  int line_chars = 0;
307 
308  switch (data_type) {
309  case NvDsDataType_FP32: {
310  const float* data = static_cast<const float*>(host_buffer);
311  for (size_t i = 0; i < elements_to_display; i++) {
312  std::stringstream value_stream;
313  value_stream << std::fixed << std::setprecision(precision) << data[i];
314  std::string value = value_stream.str();
315 
316  // If this value would exceed the line width, print the current line and start a new one
317  if (line_chars > 0 && line_chars + value.length() + 2 > valueWidth) { // +2 for ", "
318  std::cout << "| " << std::string(indent, ' ') << line.str() << std::string(valueWidth - line_chars, ' ') << " |" << std::endl;
319  line.str("");
320  line_chars = 0;
321  }
322 
323  // Add the value to the current line
324  if (line_chars > 0) {
325  line << ", ";
326  line_chars += 2;
327  }
328  line << value;
329  line_chars += value.length();
330  }
331  break;
332  }
333  case NvDsDataType_INT32: {
334  const int32_t* data = static_cast<const int32_t*>(host_buffer);
335  for (size_t i = 0; i < elements_to_display; i++) {
336  std::string value = std::to_string(data[i]);
337 
338  // If this value would exceed the line width, print the current line and start a new one
339  if (line_chars > 0 && line_chars + value.length() + 2 > valueWidth) { // +2 for ", "
340  std::cout << "| " << std::string(indent, ' ') << line.str() << std::string(valueWidth - line_chars, ' ') << " |" << std::endl;
341  line.str("");
342  line_chars = 0;
343  }
344 
345  // Add the value to the current line
346  if (line_chars > 0) {
347  line << ", ";
348  line_chars += 2;
349  }
350  line << value;
351  line_chars += value.length();
352  }
353  break;
354  }
355  case NvDsDataType_UINT32: {
356  const uint32_t* data = static_cast<const uint32_t*>(host_buffer);
357  for (size_t i = 0; i < elements_to_display; i++) {
358  std::string value = std::to_string(data[i]);
359 
360  // If this value would exceed the line width, print the current line and start a new one
361  if (line_chars > 0 && line_chars + value.length() + 2 > valueWidth) { // +2 for ", "
362  std::cout << "| " << std::string(indent, ' ') << line.str() << std::string(valueWidth - line_chars, ' ') << " |" << std::endl;
363  line.str("");
364  line_chars = 0;
365  }
366 
367  // Add the value to the current line
368  if (line_chars > 0) {
369  line << ", ";
370  line_chars += 2;
371  }
372  line << value;
373  line_chars += value.length();
374  }
375  break;
376  }
377  case NvDsDataType_INT8: {
378  const int8_t* data = static_cast<const int8_t*>(host_buffer);
379  for (size_t i = 0; i < elements_to_display; i++) {
380  std::string value = std::to_string(static_cast<int>(data[i]));
381 
382  // If this value would exceed the line width, print the current line and start a new one
383  if (line_chars > 0 && line_chars + value.length() + 2 > valueWidth) { // +2 for ", "
384  std::cout << "| " << std::string(indent, ' ') << line.str() << std::string(valueWidth - line_chars, ' ') << " |" << std::endl;
385  line.str("");
386  line_chars = 0;
387  }
388 
389  // Add the value to the current line
390  if (line_chars > 0) {
391  line << ", ";
392  line_chars += 2;
393  }
394  line << value;
395  line_chars += value.length();
396  }
397  break;
398  }
399  case NvDsDataType_UINT8: {
400  const uint8_t* data = static_cast<const uint8_t*>(host_buffer);
401  for (size_t i = 0; i < elements_to_display; i++) {
402  std::string value = std::to_string(static_cast<int>(data[i]));
403 
404  // If this value would exceed the line width, print the current line and start a new one
405  if (line_chars > 0 && line_chars + value.length() + 2 > valueWidth) { // +2 for ", "
406  std::cout << "| " << std::string(indent, ' ') << line.str() << std::string(valueWidth - line_chars, ' ') << " |" << std::endl;
407  line.str("");
408  line_chars = 0;
409  }
410 
411  // Add the value to the current line
412  if (line_chars > 0) {
413  line << ", ";
414  line_chars += 2;
415  }
416  line << value;
417  line_chars += value.length();
418  }
419  break;
420  }
421  case NvDsDataType_FP16: {
422  // FP16 display requires conversion to float
423  std::cout << "| " << std::string(indent, ' ') << "FP16 data display not fully implemented"
424  << std::string(valueWidth - 37, ' ') << "|" << std::endl;
425  break;
426  }
427  case NvDsDataType_INT64: {
428  const int64_t* data = static_cast<const int64_t*>(host_buffer);
429  for (size_t i = 0; i < elements_to_display; i++) {
430  std::string value = std::to_string(data[i]);
431 
432  // If this value would exceed the line width, print the current line and start a new one
433  if (line_chars > 0 && line_chars + value.length() + 2 > valueWidth) { // +2 for ", "
434  std::cout << "| " << std::string(indent, ' ') << line.str() << std::string(valueWidth - line_chars, ' ') << " |" << std::endl;
435  line.str("");
436  line_chars = 0;
437  }
438 
439  // Add the value to the current line
440  if (line_chars > 0) {
441  line << ", ";
442  line_chars += 2;
443  }
444  line << value;
445  line_chars += value.length();
446  }
447  break;
448  }
449  case NvDsDataType_UINT64: {
450  const uint64_t* data = static_cast<const uint64_t*>(host_buffer);
451  for (size_t i = 0; i < elements_to_display; i++) {
452  std::string value = std::to_string(data[i]);
453 
454  // If this value would exceed the line width, print the current line and start a new one
455  if (line_chars > 0 && line_chars + value.length() + 2 > valueWidth) { // +2 for ", "
456  std::cout << "| " << std::string(indent, ' ') << line.str() << std::string(valueWidth - line_chars, ' ') << " |" << std::endl;
457  line.str("");
458  line_chars = 0;
459  }
460 
461  // Add the value to the current line
462  if (line_chars > 0) {
463  line << ", ";
464  line_chars += 2;
465  }
466  line << value;
467  line_chars += value.length();
468  }
469  break;
470  }
471  default:
472  std::cout << "| " << std::string(indent, ' ') << "Unsupported data type for display"
473  << std::string(valueWidth - 32, ' ') << "|" << std::endl;
474  }
475 
476  // Print the last line if there's anything left
477  if (line_chars > 0) {
478  std::cout << "| " << std::string(indent, ' ') << line.str() << std::string(valueWidth - line_chars, ' ') << " |" << std::endl;
479  }
480 
481  // If there are more elements than we displayed, indicate that
482  if (elements_to_display < total_elements) {
483  std::cout << "|" << std::string(lineWidth+1, ' ') << "|" << std::endl;
484  std::cout << "| " << std::string(indent, ' ') << "..." << std::string(valueWidth - 3, ' ') << " |" << std::endl;
485  }
486 
487  // Add one blank line after values
488  std::cout << "|" << std::string(lineWidth+1, ' ') << "|" << std::endl;
489 
490  // Close the table
491  std::cout << headerBorder << std::endl;
492 
493  // Free CPU memory if we allocated it
494  if (is_gpu_tensor && host_buffer) {
495  free(host_buffer);
496  }
497  }
498 
499  std::cout << headerBorder << std::endl;
500  }
501 };
502 
511 class TensorCache {
512 private:
513  std::unordered_map<std::string, Tensor*> m_tensors; // Map of tensor name to tensor pointer
514 
515 public:
520 
528  releaseAll();
529  }
530 
538  bool addTensor(Tensor* tensor) {
539  if (tensor) {
540  m_tensors[tensor->name] = tensor;
541  return true;
542  }
543  return false;
544  }
545 
553  Tensor* getTensor(const std::string& name) const {
554  auto it = m_tensors.find(name);
555  if (it != m_tensors.end()) {
556  return it->second;
557  }
558  return nullptr;
559  }
560 
567  void* getTensorBuffer(const std::string& name) const {
568  auto it = m_tensors.find(name);
569  if (it != m_tensors.end() && it->second) {
570  return it->second->buffer;
571  }
572  return nullptr;
573  }
574 
581  size_t getTensorSize(const std::string& name) const {
582  auto it = m_tensors.find(name);
583  if (it != m_tensors.end() && it->second) {
584  return it->second->size;
585  }
586  return 0;
587  }
588 
595  std::vector<int> getTensorShape(const std::string& name) const {
596  auto it = m_tensors.find(name);
597  if (it != m_tensors.end() && it->second) {
598  return it->second->shape;
599  }
600  return std::vector<int>();
601  }
602 
609  int getTensorGpuId(const std::string& name) const {
610  auto it = m_tensors.find(name);
611  if (it != m_tensors.end() && it->second) {
612  return it->second->gpu_id;
613  }
614  return -1;
615  }
616 
623  int getTensorFrameNum(const std::string& name) const {
624  auto it = m_tensors.find(name);
625  if (it != m_tensors.end() && it->second) {
626  return it->second->frame_num;
627  }
628  return -1;
629  }
630 
638  torch::Tensor getTorchTensor(const std::string& name) const {
639  Tensor* tensor = getTensor(name);
640  if (tensor && tensor->buffer) {
641  return tensor->to_torch_tensor();
642  }
643  return torch::Tensor(); // Return empty tensor if not found
644  }
645 
653  bool updateTensorBuffer(const std::string& name, void* newBuffer) {
654  Tensor* tensor = getTensor(name);
655  if (!tensor) {
656  return false; // Tensor not found
657  }
658 
659  // Only update the buffer pointer, keep all other properties the same
660  tensor->buffer = newBuffer;
661 
662  return true;
663  }
664 
675  Tensor* cloneTensorCPU(const std::string& name) {
676  // Get the source tensor
677  Tensor* srcTensor = getTensor(name);
678  if (!srcTensor || !srcTensor->buffer || srcTensor->size == 0) {
679  return nullptr; // Source tensor not found or invalid
680  }
681 
682  std::string cpu_tensor_name = srcTensor->name + "_cpu";
683  Tensor* cpuTensor = nullptr;
684 
685  // Check if the CPU tensor already exists
686  if (hasTensor(cpu_tensor_name)) {
687  // If it exists, use the already allocated CPU tensor
688  cpuTensor = getTensor(cpu_tensor_name);
689  } else{
690  // Create a new tensor with the same properties
691  cpuTensor = new Tensor();
692  cpuTensor->name = cpu_tensor_name;
693  cpuTensor->shape = srcTensor->shape;
694  cpuTensor->data_type = srcTensor->data_type;
695  cpuTensor->size = srcTensor->size;
696  cpuTensor->gpu_id = -1;
697 
698  // Allocate CPU memory
699  cpuTensor->buffer = malloc(srcTensor->size);
700  if (!cpuTensor->buffer) {
701  delete cpuTensor;
702  std::cerr << "Failed to allocate CPU memory for tensor clone" << std::endl;
703  return nullptr;
704  }
705 
706  // Add the new tensor to the cache
707  m_tensors[cpu_tensor_name] = cpuTensor;
708  }
709 
710  // Update frame number
711  cpuTensor->frame_num = srcTensor->frame_num;
712 
713  // Copy data from source tensor to CPU tensor
714  if (srcTensor->gpu_id >= 0) {
715  // Source is on GPU, need GPU to CPU copy
716  cudaError_t copyError = cudaMemcpy(
717  cpuTensor->buffer, // Destination: CPU buffer
718  srcTensor->buffer, // Source: GPU buffer
719  srcTensor->size, // Size to copy
720  cudaMemcpyDeviceToHost // GPU to CPU copy
721  );
722 
723  if (copyError != cudaSuccess) {
724  std::cerr << "Failed to copy tensor from GPU to CPU: "
725  << cudaGetErrorString(copyError) << std::endl;
726  free(cpuTensor->buffer);
727  delete cpuTensor;
728  return nullptr;
729  }
730  } else {
731  // Source is already on CPU, do a CPU to CPU copy
732  memcpy(cpuTensor->buffer, srcTensor->buffer, srcTensor->size);
733  }
734 
735  return cpuTensor;
736  }
737 
749  inline torch::Tensor cloneTorchTensorCPU(const std::string& name) {
750  // Get a CPU clone of the tensor
751  Tensor* cpuTensor = cloneTensorCPU(name);
752  if (!cpuTensor) {
753  return torch::Tensor(); // Return empty tensor if clone failed
754  }
755 
756  // Convert to PyTorch tensor
757  return cpuTensor->to_torch_tensor();
758  }
759 
766  bool hasTensor(const std::string& name) const {
767  return m_tensors.find(name) != m_tensors.end();
768  }
769 
776  bool removeTensor(const std::string& name) {
777  auto it = m_tensors.find(name);
778  if (it != m_tensors.end()) {
779  if (it->second) {
780  // Use release() to properly free memory based on whether it's CPU or GPU
781  it->second->release();
782  delete it->second; // Delete the tensor object
783  }
784  m_tensors.erase(it);
785  return true;
786  }
787  return false;
788  }
789 
793  void releaseAll() {
794  for (auto& pair : m_tensors) {
795  // Skip img tensor
796  if (pair.first == "img") {
797  continue;
798  }
799 
800  if (pair.second) {
801  // Use release() to properly free memory based on whether it's CPU or GPU
802  pair.second->release();
803  delete pair.second; // Delete the tensor object
804  }
805  }
806  m_tensors.clear();
807  }
808 
814  size_t size() const {
815  return m_tensors.size();
816  }
817 
823  std::vector<std::string> getTensorNames() const {
824  std::vector<std::string> names;
825  names.reserve(m_tensors.size());
826  for (const auto& pair : m_tensors) {
827  names.push_back(pair.first);
828  }
829  return names;
830  }
831 
837  const std::unordered_map<std::string, Tensor*>& getTensors() const {
838  return m_tensors;
839  }
840 
846  void display(bool print_data = false) const {
847  for (const auto& pair : m_tensors) {
848  if (pair.second) {
849  pair.second->display(print_data);
850  } else {
851  std::cout << " [NULL TENSOR]" << std::endl;
852  }
853  }
854  }
855 
862  void displayTensor(const std::string& name, bool print_data = false) const {
863  auto it = m_tensors.find(name);
864  if (it != m_tensors.end() && it->second) {
865  it->second->display(print_data);
866  } else {
867  std::cout << " [NULL TENSOR]" << std::endl;
868  }
869  }
870 
871 };
872 
882 inline std::string torch_tensor_sizes_to_string(const torch::Tensor& tensor) {
883  if (!tensor.defined()) {
884  return "[undefined]";
885  }
886 
887  std::stringstream ss;
888  ss << "[";
889  for (size_t i = 0; i < tensor.sizes().size(); ++i) {
890  ss << tensor.sizes()[i];
891  if (i < tensor.sizes().size() - 1) {
892  ss << "x";
893  }
894  }
895  ss << "]";
896  return ss.str();
897 }
898 
909 inline std::string torch_tensor_to_string(const torch::Tensor& tensor, int max_values = 10) {
910  // Check if tensor is valid
911  if (!tensor.defined()) {
912  return "[undefined tensor]";
913  }
914 
915  // Create a copy to avoid modifying the original tensor
916  auto t = tensor.clone().contiguous().cpu();
917 
918  std::stringstream ss;
919  ss << "[";
920 
921  // Determine how many values to print
922  int64_t num_to_print;
923  bool show_ellipsis;
924 
925  if (max_values == -1) {
926  // Print all elements when max_values is -1
927  num_to_print = t.numel();
928  show_ellipsis = false;
929  } else {
930  // Print limited number of elements
931  num_to_print = std::min(static_cast<int64_t>(max_values), t.numel());
932  show_ellipsis = num_to_print < t.numel();
933  }
934 
935  // Return early for empty tensors
936  if (t.numel() == 0) {
937  ss << "]";
938  return ss.str();
939  }
940 
941  // Handle different tensor types
942  if (t.scalar_type() == torch::ScalarType::Float) {
943  auto a = t.data_ptr<float>();
944  for (int64_t i = 0; i < num_to_print; i++) {
945  ss << a[i];
946  if (i < num_to_print - 1) {
947  ss << ", ";
948  }
949  }
950  } else if (t.scalar_type() == torch::ScalarType::Int) {
951  auto a = t.data_ptr<int32_t>();
952  for (int64_t i = 0; i < num_to_print; i++) {
953  ss << a[i];
954  if (i < num_to_print - 1) {
955  ss << ", ";
956  }
957  }
958  } else if (t.scalar_type() == torch::ScalarType::Long) {
959  auto a = t.data_ptr<int64_t>();
960  for (int64_t i = 0; i < num_to_print; i++) {
961  ss << a[i];
962  if (i < num_to_print - 1) {
963  ss << ", ";
964  }
965  }
966  } else {
967  // Fallback for other types
968  ss << "tensor(" << t.sizes() << ")";
969  show_ellipsis = false;
970  }
971 
972  // Add ellipsis if tensor has more elements than we're showing
973  if (show_ellipsis) {
974  ss << ", ...";
975  }
976 
977  ss << "]";
978  return ss.str();
979 }
980 
995 inline void processDataType(
996  std::ifstream& file,
997  Tensor* result,
998  const std::string& dtype,
999  int64_t num_elements,
1000  const std::vector<int64_t>& shape_int64,
1001  const std::string& file_path,
1002  int gpu_id) {
1003 
1004  cudaError_t cuda_status;
1005 
1006  // Process float32 data
1007  if (dtype.find("float32") != std::string::npos) {
1008  result->data_type = NvDsDataType_FP32;
1009  size_t element_size = sizeof(float);
1010 
1011  // Allocate memory for reading data on CPU
1012  std::vector<float> cpu_data(num_elements);
1013  file.read(reinterpret_cast<char*>(cpu_data.data()), num_elements * element_size);
1014 
1015  // Allocate GPU memory
1016  result->size = num_elements * element_size;
1017  cuda_status = cudaMalloc(&result->buffer, result->size);
1018  if (cuda_status != cudaSuccess) {
1019  std::cerr << "Error allocating GPU memory: "
1020  << cudaGetErrorString(cuda_status) << std::endl;
1021  return;
1022  }
1023 
1024  // Copy data from CPU to GPU
1025  cuda_status = cudaMemcpy(result->buffer, cpu_data.data(), result->size, cudaMemcpyHostToDevice);
1026  if (cuda_status != cudaSuccess) {
1027  std::cerr << "Error copying data to GPU: "
1028  << cudaGetErrorString(cuda_status) << std::endl;
1029  cudaFree(result->buffer);
1030  result->buffer = nullptr;
1031  return;
1032  }
1033  }
1034 }
1035 
1057 inline Tensor* read_tensor_from_file(const std::string& file_path, int gpu_id = 0) {
1058  // Initialize result tensor
1059  Tensor* result = new Tensor();
1060  result->name = "tensor_from_file";
1061  result->gpu_id = gpu_id;
1062 
1063  // Open file
1064  std::ifstream file(file_path, std::ios::binary);
1065  if (!file.is_open()) {
1066  std::cerr << "Error: Could not open file: " << file_path << std::endl;
1067  return result; // Return empty tensor with valid pointer but no data
1068  }
1069 
1070  try {
1071  // Read tensor metadata from file header
1072 
1073  int64_t num_dims;
1074  file.read(reinterpret_cast<char*>(&num_dims), sizeof(int64_t));
1075 
1076  // Read shape dimensions
1077  std::vector<int64_t> shape_int64(num_dims);
1078  file.read(reinterpret_cast<char*>(shape_int64.data()), num_dims * sizeof(int64_t));
1079 
1080  // Convert int64_t shape to int shape for our Tensor struct
1081  result->shape.resize(num_dims);
1082  for (int64_t i = 0; i < num_dims; ++i) {
1083  result->shape[i] = static_cast<int>(shape_int64[i]);
1084  }
1085 
1086  // Read dtype string length
1087  int64_t dtype_str_len;
1088  file.read(reinterpret_cast<char*>(&dtype_str_len), sizeof(int64_t));
1089 
1090  // Read dtype string
1091  std::vector<char> dtype_str(dtype_str_len + 1, 0); // +1 for null terminator
1092  file.read(dtype_str.data(), dtype_str_len);
1093  std::string dtype(dtype_str.data());
1094 
1095  // Calculate total number of elements
1096  int64_t num_elements = 1;
1097  for (int64_t dim : shape_int64) {
1098  num_elements *= dim;
1099  }
1100 
1101  // Set CUDA device
1102  cudaError_t cuda_status = cudaSetDevice(gpu_id);
1103  if (cuda_status != cudaSuccess) {
1104  std::cerr << "Error setting CUDA device " << gpu_id << ": "
1105  << cudaGetErrorString(cuda_status) << std::endl;
1106  return result; // Return empty tensor
1107  }
1108 
1109  // Process different data types
1110  processDataType(file, result, dtype, num_elements, shape_int64, file_path, gpu_id);
1111 
1112  return result;
1113  }
1114  catch (const std::exception& e) {
1115  std::cerr << "Error reading tensor from file: " << e.what() << std::endl;
1116  if (result->buffer) {
1117  cudaFree(result->buffer);
1118  result->buffer = nullptr;
1119  }
1120  return result; // Return empty tensor
1121  }
1122 }
1123 
1136 inline void torch_tensor_display(const torch::Tensor& tensor,
1137  const std::string& name = "Tensor",
1138  bool print_data = false,
1139  size_t max_elements = 100,
1140  int precision = 4) {
1141  if (!tensor.defined()) {
1142  std::cout << "Undefined tensor" << std::endl;
1143  return;
1144  }
1145 
1146  // Table formatting constants
1147  const int lineWidth = 100;
1148  const std::string headerBorder = "+" + std::string(lineWidth+1, '-') + "+";
1149  const int labelWidth = 16;
1150  const int valueWidth = lineWidth - labelWidth - 3; // -3 for "| " and " |"
1151  const int indent = 2;
1152 
1153  std::cout << "\n" << headerBorder << std::endl;
1154 
1155  // Create header with tensor name
1156  std::string headerText = "Tensor Information - " + name;
1157  int padding = (lineWidth - headerText.length()) / 2;
1158  std::cout << "| " << std::string(padding, ' ') << headerText
1159  << std::string(lineWidth - padding - headerText.length(), ' ') << "|" << std::endl;
1160 
1161  std::cout << headerBorder << std::endl;
1162 
1163  // Get tensor properties
1164  auto sizes = tensor.sizes();
1165  auto dtype = tensor.scalar_type();
1166  auto device = tensor.device();
1167  size_t numel = tensor.numel();
1168  size_t elements_to_display = std::min(numel, max_elements);
1169 
1170  // Format shape as string
1171  std::string shapeStr = "[";
1172  for (size_t i = 0; i < sizes.size(); i++) {
1173  shapeStr += std::to_string(sizes[i]);
1174  if (i < sizes.size() - 1) shapeStr += ", ";
1175  }
1176  shapeStr += "]";
1177 
1178  // Convert dtype to string
1179  std::string dtypeStr;
1180  switch (dtype) {
1181  case torch::kFloat32: dtypeStr = "Float32"; break;
1182  case torch::kFloat16: dtypeStr = "Float16"; break;
1183  case torch::kFloat64: dtypeStr = "Float64"; break;
1184  case torch::kInt32: dtypeStr = "Int32"; break;
1185  case torch::kInt64: dtypeStr = "Int64"; break;
1186  case torch::kInt16: dtypeStr = "Int16"; break;
1187  case torch::kInt8: dtypeStr = "Int8"; break;
1188  case torch::kUInt8: dtypeStr = "UInt8"; break;
1189  case torch::kBool: dtypeStr = "Bool"; break;
1190  default: dtypeStr = "Unknown"; break;
1191  }
1192 
1193  // Format device information
1194  std::string deviceStr;
1195  if (device.is_cuda()) {
1196  deviceStr = "GPU [" + std::to_string(device.index()) + "]";
1197  } else {
1198  deviceStr = "CPU";
1199  }
1200 
1201  // Calculate memory size (approximate)
1202  size_t element_size = 0;
1203  switch (dtype) {
1204  case torch::kFloat32: element_size = 4; break;
1205  case torch::kFloat16: element_size = 2; break;
1206  case torch::kFloat64: element_size = 8; break;
1207  case torch::kInt32: element_size = 4; break;
1208  case torch::kInt64: element_size = 8; break;
1209  case torch::kInt16: element_size = 2; break;
1210  case torch::kInt8: element_size = 1; break;
1211  case torch::kUInt8: element_size = 1; break;
1212  case torch::kBool: element_size = 1; break;
1213  default: element_size = 4; break;
1214  }
1215  size_t memory_size = numel * element_size;
1216 
1217  // Display tensor properties
1218  std::cout << "| Shape | " << std::left << std::setw(valueWidth) << shapeStr << " |" << std::endl;
1219  std::cout << "| Device | " << std::left << std::setw(valueWidth) << deviceStr << " |" << std::endl;
1220  std::cout << "| Memory Size | " << std::left << std::setw(valueWidth) << std::to_string(memory_size) + " bytes" << " |" << std::endl;
1221  std::cout << "| Elements | " << std::left << std::setw(valueWidth) << std::to_string(numel) << " |" << std::endl;
1222  std::cout << "| Data Type | " << std::left << std::setw(valueWidth) << dtypeStr << " |" << std::endl;
1223  std::cout << "| Requires Grad | " << std::left << std::setw(valueWidth) << (tensor.requires_grad() ? "True" : "False") << " |" << std::endl;
1224 
1225  // Print tensor data values if requested
1226  if (print_data && numel > 0) {
1227  // Ensure tensor is on CPU for display
1228  torch::Tensor cpu_tensor = tensor.device().is_cuda() ? tensor.to(torch::kCPU) : tensor;
1229 
1230  // Create contiguous version for easier access
1231  cpu_tensor = cpu_tensor.contiguous();
1232 
1233  // Divider before data section
1234  std::cout << "|" << std::string(lineWidth+1, '-') << "|" << std::endl;
1235 
1236  if (tensor.device().is_cuda()) {
1237  std::cout << "| Values [GPU --> CPU]:" << std::string(lineWidth - 21, ' ') << "|" << std::endl;
1238  } else {
1239  std::cout << "| Values [CPU]:" << std::string(lineWidth - 13, ' ') << "|" << std::endl;
1240  }
1241 
1242  // Add one blank line before values
1243  std::cout << "|" << std::string(lineWidth+1, ' ') << "|" << std::endl;
1244 
1245  // Set floating point precision
1246  std::cout << std::fixed << std::setprecision(precision);
1247 
1248  // Prepare all values as strings first
1249  std::vector<std::string> value_strings;
1250  value_strings.reserve(elements_to_display);
1251 
1252  // Convert tensor data to strings based on type
1253  if (dtype == torch::kFloat32) {
1254  auto data_ptr = cpu_tensor.data_ptr<float>();
1255  for (size_t i = 0; i < elements_to_display; i++) {
1256  std::stringstream ss;
1257  ss << std::fixed << std::setprecision(precision) << data_ptr[i];
1258  value_strings.push_back(ss.str());
1259  }
1260  } else if (dtype == torch::kInt32) {
1261  auto data_ptr = cpu_tensor.data_ptr<int32_t>();
1262  for (size_t i = 0; i < elements_to_display; i++) {
1263  value_strings.push_back(std::to_string(data_ptr[i]));
1264  }
1265  } else if (dtype == torch::kInt64) {
1266  auto data_ptr = cpu_tensor.data_ptr<int64_t>();
1267  for (size_t i = 0; i < elements_to_display; i++) {
1268  value_strings.push_back(std::to_string(data_ptr[i]));
1269  }
1270  } else if (dtype == torch::kUInt8 || dtype == torch::kInt8) {
1271  auto data_ptr = cpu_tensor.data_ptr<uint8_t>();
1272  for (size_t i = 0; i < elements_to_display; i++) {
1273  value_strings.push_back(std::to_string(static_cast<int>(data_ptr[i])));
1274  }
1275  } else if (dtype == torch::kBool) {
1276  auto data_ptr = cpu_tensor.data_ptr<bool>();
1277  for (size_t i = 0; i < elements_to_display; i++) {
1278  value_strings.push_back(data_ptr[i] ? "true" : "false");
1279  }
1280  } else if (dtype == torch::kFloat16) {
1281  std::cout << "| " << std::string(indent, ' ') << "Float16 data display not fully implemented"
1282  << std::string(valueWidth - 37, ' ') << "|" << std::endl;
1283  std::cout << "|" << std::string(lineWidth+1, ' ') << "|" << std::endl;
1284  std::cout << headerBorder << std::endl;
1285  return;
1286  } else {
1287  std::cout << "| " << std::string(indent, ' ') << "Unsupported data type for display"
1288  << std::string(valueWidth - 32, ' ') << "|" << std::endl;
1289  std::cout << "|" << std::string(lineWidth+1, ' ') << "|" << std::endl;
1290  std::cout << headerBorder << std::endl;
1291  return;
1292  }
1293 
1294  // Format values into lines with proper wrapping
1295  const int max_line_width = lineWidth - 2 * indent - 4; // -4 for "| " and " |"
1296  std::string current_line;
1297  int current_line_width = 0;
1298 
1299  for (size_t i = 0; i < value_strings.size(); i++) {
1300  std::string value = value_strings[i];
1301  std::string entry = value;
1302 
1303  // Add comma if not the last element
1304  if (i < value_strings.size() - 1) {
1305  entry += ", ";
1306  }
1307 
1308  int entry_width = entry.length();
1309 
1310  // Check if adding this entry would exceed the line width
1311  if (current_line_width > 0 && current_line_width + entry_width > max_line_width) {
1312  // Print current line and start a new one
1313  std::cout << "| " << std::string(indent, ' ') << std::left
1314  << std::setw(lineWidth - 3) << current_line << " |" << std::endl;
1315  current_line = entry;
1316  current_line_width = entry_width;
1317  } else {
1318  // Add to current line
1319  current_line += entry;
1320  current_line_width += entry_width;
1321  }
1322  }
1323 
1324  // Print the last line if anything left
1325  if (current_line_width > 0) {
1326  std::cout << "| " << std::string(indent, ' ') << std::left
1327  << std::setw(lineWidth - 3) << current_line << " |" << std::endl;
1328  }
1329 
1330  // If there are more elements than displayed, add ellipsis
1331  if (elements_to_display < numel) {
1332  std::cout << "|" << std::string(lineWidth+1, ' ') << "|" << std::endl;
1333  std::cout << "| " << std::string(indent, ' ') << "..."
1334  << std::string(lineWidth - indent - 5, ' ') << " |" << std::endl;
1335  }
1336 
1337  // Add one blank line after values
1338  std::cout << "|" << std::string(lineWidth+1, ' ') << "|" << std::endl;
1339  }
1340 
1341  // Close the table
1342  std::cout << headerBorder << std::endl;
1343 }
1344 
1345 #endif /* TENSOR_H */
Tensor::data_type
NvDsDataType data_type
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:45
TensorCache::cloneTorchTensorCPU
torch::Tensor cloneTorchTensorCPU(const std::string &name)
Clone a tensor to CPU memory and convert to PyTorch tensor.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:749
torch_tensor_display
void torch_tensor_display(const torch::Tensor &tensor, const std::string &name="Tensor", bool print_data=false, size_t max_elements=100, int precision=4)
Display a PyTorch tensor in a formatted table.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:1136
Tensor::size
size_t size
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:43
TensorCache
Class to manage multiple tensors with string-based lookup.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:511
Tensor::release
bool release()
Release GPU memory associated with this tensor.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:130
NvDsDataType_INT32
@ NvDsDataType_INT32
INT32 data type.
Definition: includes/nvds_roi_meta.h:70
TensorCache::addTensor
bool addTensor(Tensor *tensor)
Add a tensor to the cache.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:538
read_tensor_from_file
Tensor * read_tensor_from_file(const std::string &file_path, int gpu_id=0)
Read a tensor from a binary file created by dump_tensor_to_file.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:1057
TensorCache::cloneTensorCPU
Tensor * cloneTensorCPU(const std::string &name)
Clone a tensor to CPU memory.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:675
NvDsDataType_INT8
@ NvDsDataType_INT8
INT8 data type.
Definition: includes/nvds_roi_meta.h:66
Tensor::Tensor
Tensor()
Default constructor initializing members to safe defaults.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:52
NvDsDataType_FP16
@ NvDsDataType_FP16
FP16 data type.
Definition: includes/nvds_roi_meta.h:76
NvDsDataType_UINT32
@ NvDsDataType_UINT32
UINT32 data type.
Definition: includes/nvds_roi_meta.h:68
NvDsDataType_INT64
@ NvDsDataType_INT64
INT64 data type.
Definition: includes/nvds_roi_meta.h:72
NvDsDataType_UINT8
@ NvDsDataType_UINT8
UINT8 data type.
Definition: includes/nvds_roi_meta.h:64
half_float::detail::binary
HALF_CONSTEXPR_CONST binary_t binary
Tag for binary construction.
Definition: includes/half.hpp:553
TensorCache::getTensorFrameNum
int getTensorFrameNum(const std::string &name) const
Get a tensor's frame_num by name.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:623
TensorCache::hasTensor
bool hasTensor(const std::string &name) const
Check if a tensor with the given name exists.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:766
TensorCache::getTensorNames
std::vector< std::string > getTensorNames() const
Get a list of all tensor names in the cache.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:823
TensorCache::releaseAll
void releaseAll()
Release all tensors and clear the cache.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:793
TensorCache::getTorchTensor
torch::Tensor getTorchTensor(const std::string &name) const
Get a tensor directly as PyTorch tensor by name.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:638
NvDsDataType_UINT64
@ NvDsDataType_UINT64
UINT64 data type.
Definition: includes/nvds_roi_meta.h:74
TensorCache::updateTensorBuffer
bool updateTensorBuffer(const std::string &name, void *newBuffer)
Update only a tensor's buffer pointer, keeping all other properties the same.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:653
TensorCache::removeTensor
bool removeTensor(const std::string &name)
Remove a tensor from the cache and release its resources.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:776
torch_tensor_sizes_to_string
std::string torch_tensor_sizes_to_string(const torch::Tensor &tensor)
Provide a string representation of the sizes of a torch tensor.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:882
processDataType
void processDataType(std::ifstream &file, Tensor *result, const std::string &dtype, int64_t num_elements, const std::vector< int64_t > &shape_int64, const std::string &file_path, int gpu_id)
Helper function to process tensor data based on its type.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:995
pydeepstreamdoc::tensor::TensorDoc::size
constexpr const char * size
Definition: service-maker/sources/python/src/bindings/docstrings/tensordoc.h:46
TensorCache::TensorCache
TensorCache()
Default constructor.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:519
Tensor
Structure to store tensor information.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:40
TensorCache::getTensorGpuId
int getTensorGpuId(const std::string &name) const
Get a tensor's gpu_id by name.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:609
Tensor::frame_num
int frame_num
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:47
Tensor::gpu_id
int gpu_id
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:46
TensorCache::getTensor
Tensor * getTensor(const std::string &name) const
Get a tensor by name.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:553
TensorCache::display
void display(bool print_data=false) const
Display information about all cached tensors.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:846
Tensor::to_torch_tensor
torch::Tensor to_torch_tensor() const
Convert Tensor to PyTorch tensor.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:63
min
int min(int a, int b)
Compute the component-wise minimum.
Definition: sources/libs/nvmultiobjecttracker/include/modules/cuDCFv2/helper_math.h:70
TensorCache::getTensorShape
std::vector< int > getTensorShape(const std::string &name) const
Get a tensor's shape by name.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:595
torch_tensor_to_string
std::string torch_tensor_to_string(const torch::Tensor &tensor, int max_values=10)
Convert torch tensor to string representation of its values.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:909
TensorCache::displayTensor
void displayTensor(const std::string &name, bool print_data=false) const
Display information about given tensor.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:862
TensorCache::~TensorCache
~TensorCache()
Destructor that automatically releases all cached tensors.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:527
NvDsDataType_FP32
@ NvDsDataType_FP32
FP32 data type.
Definition: includes/nvds_roi_meta.h:62
Tensor::~Tensor
~Tensor() noexcept
Destructor to automatically release resources.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:167
Tensor::display
void display(bool print_data=false) const
Display metadata information about this tensor in a formatted table.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:174
TensorCache::getTensorBuffer
void * getTensorBuffer(const std::string &name) const
Get a tensor's buffer by name.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:567
Tensor::buffer
void * buffer
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:42
data
JSAMPIMAGE data
Definition: sources/libs/nvll_batch_jpeg_encode/oss/jpeglib.h:967
Tensor::shape
std::vector< int > shape
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:44
TensorCache::getTensors
const std::unordered_map< std::string, Tensor * > & getTensors() const
Get all tensors in the cache.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:837
TensorCache::getTensorSize
size_t getTensorSize(const std::string &name) const
Get a tensor's size by name.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:581
Tensor::name
std::string name
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:41
NvDsDataType
NvDsDataType
Data type used for model in infer.
Definition: includes/nvds_roi_meta.h:59
TensorCache::size
size_t size() const
Get the number of tensors in the cache.
Definition: sources/gst-plugins/gst-nvdsvideotemplate/ds-sparse4d/utils/tensor.h:814