Open3D (C++ API)  0.18.0+252c867
MemoryAllocation.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - Open3D: www.open3d.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2023 www.open3d.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #pragma once
9 
10 #include <iostream>
11 #include <memory>
12 #include <stdexcept>
13 #include <utility>
14 #include <vector>
15 
16 namespace open3d {
17 namespace ml {
18 namespace impl {
19 
22 public:
30  MemoryAllocation(void* ptr, size_t size, size_t alignment = 1)
31  : _ptr(ptr),
32  _size(size),
33  _alignment(alignment),
34  _max_size_ptr((char*)ptr) {
35  // align start and end of memory segment
36  void* aligned_ptr = std::align(_alignment, 1, ptr, size);
37  size_t size_after_align =
38  (((char*)ptr + size) - (char*)aligned_ptr) / _alignment;
39  size_after_align *= _alignment;
40  _free_segments.push_back(
41  std::pair<void*, size_t>(aligned_ptr, size_after_align));
42  }
43 
47  template <class T>
48  std::pair<T*, size_t> Alloc(size_t size) {
49  std::pair<void*, size_t> tmp = Alloc(size * sizeof(T));
50  return std::pair<T*, size_t>((T*)tmp.first, tmp.first ? size : 0);
51  }
52 
55  std::pair<void*, size_t> Alloc(size_t size) {
56  // round up to alignment
57  if (size % _alignment) size += _alignment - size % _alignment;
58 
59  for (size_t i = 0; i < _free_segments.size(); ++i) {
60  void* ptr = std::align(_alignment, size, _free_segments[i].first,
61  _free_segments[i].second);
62  if (ptr) {
63  char* end_ptr = (char*)ptr + size;
64  if (end_ptr > _max_size_ptr) _max_size_ptr = end_ptr;
65 
66  _free_segments[i].first = end_ptr;
67  _free_segments[i].second -= size;
68  return std::pair<void*, size_t>(ptr, size);
69  }
70  }
71  return std::pair<void*, size_t>(nullptr, 0);
72  }
73 
75  std::pair<void*, size_t> AllocLargestSegment() {
76  size_t size = 0;
77  for (const auto& s : _free_segments)
78  if (s.second > size) size = s.second;
79 
80  return Alloc(size);
81  }
82 
84  template <class T>
85  void Free(const std::pair<T*, size_t>& segment) {
86  size_t size = sizeof(T) * segment.second;
87  if (size % _alignment) size += _alignment - size % _alignment;
88 
89  Free(std::pair<void*, size_t>(segment.first, size));
90  }
91 
93  void Free(const std::pair<void*, size_t>& segment) {
94  if (DEBUG) {
95  if ((char*)segment.first < (char*)_ptr ||
96  (char*)segment.first + segment.second > (char*)_ptr + _size)
97  throw std::runtime_error("free(): segment is out of bounds");
98  }
99  {
100  size_t i;
101  for (i = 0; i < _free_segments.size(); ++i) {
102  if ((char*)segment.first < (char*)_free_segments[i].first)
103  break;
104  }
105  _free_segments.insert(_free_segments.begin() + i, segment);
106  }
107 
108  // merge adjacent segments
109  auto seg = _free_segments[0];
110  char* end_ptr = (char*)seg.first + seg.second;
111  size_t count = 0;
112  for (size_t i = 1; i < _free_segments.size(); ++i) {
113  const auto& seg_i = _free_segments[i];
114 
115  if (end_ptr == (char*)seg_i.first) {
116  // merge with adjacent following segment
117  seg.second += seg_i.second;
118  end_ptr = (char*)seg.first + seg.second;
119  } else {
120  _free_segments[count] = seg;
121  seg = _free_segments[i];
122  end_ptr = (char*)seg.first + seg.second;
123  ++count;
124  }
125  }
126  _free_segments[count] = seg;
127  ++count;
128  _free_segments.resize(count);
129 
130  if (DEBUG) {
131  // check if there are overlapping segments
132  for (size_t i = 1; i < _free_segments.size(); ++i) {
133  char* prev_end_ptr = (char*)_free_segments[i - 1].first +
134  _free_segments[i - 1].second;
135  if (prev_end_ptr > (char*)_free_segments[i].first) {
136  throw std::runtime_error(
137  "free(): Overlapping free segments found after "
138  "call to free");
139  }
140  }
141  }
142  }
143 
145  size_t MaxUsed() const { return _max_size_ptr - (char*)_ptr; }
146 
148  size_t Alignment() const { return _alignment; }
149 
151  const std::vector<std::pair<void*, size_t>>& FreeSegments() const {
152  return _free_segments;
153  }
154 
156  template <class T>
157  static void PrintSegment(const std::pair<T*, size_t>& s) {
158  std::cerr << "ptr " << (void*)s.first << "\t size " << s.second
159  << "\t end " << (void*)((char*)s.first + s.second) << "\n";
160  }
161 
163  void PrintFreeSegments() const {
164  for (const auto& s : _free_segments) PrintSegment(s);
165  }
166 
167 private:
168  enum internal_config { DEBUG = 0 };
169 
171  const void* _ptr;
172 
174  const size_t _size;
175 
177  const size_t _alignment;
178 
180  char* _max_size_ptr;
181 
184  std::vector<std::pair<void*, size_t>> _free_segments;
185 };
186 
187 } // namespace impl
188 } // namespace ml
189 } // namespace open3d
A class for managing memory segments within a memory allocation.
Definition: MemoryAllocation.h:21
size_t Alignment() const
Returns the alignment in bytes.
Definition: MemoryAllocation.h:148
void Free(const std::pair< T *, size_t > &segment)
Frees a previously returned segment.
Definition: MemoryAllocation.h:85
MemoryAllocation(void *ptr, size_t size, size_t alignment=1)
Definition: MemoryAllocation.h:30
std::pair< void *, size_t > Alloc(size_t size)
Definition: MemoryAllocation.h:55
static void PrintSegment(const std::pair< T *, size_t > &s)
Prints the segment. Meant for debugging.
Definition: MemoryAllocation.h:157
void Free(const std::pair< void *, size_t > &segment)
Frees a previously returned segment.
Definition: MemoryAllocation.h:93
const std::vector< std::pair< void *, size_t > > & FreeSegments() const
Returns the list of free segments.
Definition: MemoryAllocation.h:151
std::pair< void *, size_t > AllocLargestSegment()
Returns the largest free segment.
Definition: MemoryAllocation.h:75
void PrintFreeSegments() const
Prints all free segments. Meant for debugging.
Definition: MemoryAllocation.h:163
std::pair< T *, size_t > Alloc(size_t size)
Definition: MemoryAllocation.h:48
size_t MaxUsed() const
Returns the peak memory usage in bytes.
Definition: MemoryAllocation.h:145
int size
Definition: FilePCD.cpp:40
int count
Definition: FilePCD.cpp:42
Definition: PinholeCameraIntrinsic.cpp:16