]> rtime.felk.cvut.cz Git - hercules2020/kcf.git/blob - src/dynmem.hpp
Remove debug printf
[hercules2020/kcf.git] / src / dynmem.hpp
1 #ifndef DYNMEM_HPP
2 #define DYNMEM_HPP
3
4 #include <cstdlib>
5 #include <opencv2/opencv.hpp>
6 #include <cassert>
7 #include <numeric>
8 #include <mutex>
9 #include <stack>
10
11 #if defined(CUFFT) || defined(CUFFTW)
12 #include "cuda_runtime.h"
13 #ifdef CUFFT
14 #include "cuda_error_check.hpp"
15 #endif
16 #endif
17
18 class MemoryManager {
19     std::mutex mutex;
20     std::map<size_t, std::stack<void*> > map;
21
22 public:
23     void *get(size_t size) {
24         std::lock_guard<std::mutex> guard(mutex);
25         auto &stack = map[size];
26         void *ptr = nullptr;
27         if (!stack.empty()) {
28             ptr = stack.top();
29             stack.pop();
30         }
31         return ptr;
32     }
33     void put(void *ptr, size_t size) {
34         std::lock_guard<std::mutex> guard(mutex);
35         map[size].push(ptr);
36     }
37 };
38
39 template <typename T> class DynMem_ {
40   private:
41     T *ptr_h = nullptr;
42 #ifdef CUFFT
43     T *ptr_d = nullptr;
44     static MemoryManager mmng;
45 #endif
46   public:
47     typedef T value_type;
48     const size_t num_elem;
49
50     DynMem_(size_t num_elem) : num_elem(num_elem)
51     {
52 #ifdef CUFFT
53         ptr_h = reinterpret_cast<T*>(mmng.get(num_elem));
54         if (!ptr_h)
55             CudaSafeCall(cudaHostAlloc(reinterpret_cast<void **>(&ptr_h), num_elem * sizeof(T), cudaHostAllocMapped));
56
57         CudaSafeCall(cudaHostGetDevicePointer(reinterpret_cast<void **>(&ptr_d), reinterpret_cast<void *>(ptr_h), 0));
58 #else
59         ptr_h = new T[num_elem];
60 #endif
61     }
62     DynMem_(const DynMem_ &other) : DynMem_(other.num_elem)
63     {
64         memcpy(ptr_h, other.ptr_h, num_elem * sizeof(T));
65     }
66     DynMem_(DynMem_ &&other) : num_elem(other.num_elem)
67     {
68         ptr_h = other.ptr_h;
69         other.ptr_h = nullptr;
70 #ifdef CUFFT
71         ptr_d = other.ptr_d;
72         other.ptr_d = nullptr;
73 #endif
74     }
75     ~DynMem_()
76     {
77         release();
78     }
79     T *hostMem() { return ptr_h; }
80     const T *hostMem() const { return ptr_h; }
81 #ifdef CUFFT
82     T *deviceMem() { return ptr_d; }
83     const T *deviceMem() const { return ptr_d; }
84 #endif
85     void operator=(DynMem_ &rhs) {
86         assert(num_elem == rhs.num_elem);
87         memcpy(ptr_h, rhs.ptr_h, num_elem * sizeof(T));
88     }
89     void operator=(DynMem_ &&rhs)
90     {
91         assert(num_elem == rhs.num_elem);
92         release();
93         ptr_h = rhs.ptr_h;
94         rhs.ptr_h = nullptr;
95 #ifdef CUFFT
96         ptr_d = rhs.ptr_d;
97         rhs.ptr_d = nullptr;
98 #endif
99     }
100     T operator[](uint i) const { return ptr_h[i]; }
101 private:
102     void release()
103     {
104 #ifdef CUFFT
105         if (ptr_h)
106             mmng.put(ptr_h, num_elem);
107         //CudaSafeCall(cudaFreeHost(ptr_h));
108 #else
109         delete[] ptr_h;
110 #endif
111     }
112 };
113
114 #ifdef CUFFT
115 template <typename T>
116 MemoryManager DynMem_<T>::mmng;
117 #endif
118
119 typedef DynMem_<float> DynMem;
120
121
122 class MatDynMem : public DynMem, public cv::Mat {
123   public:
124     MatDynMem(cv::Size size, int type)
125         : DynMem(size.area() * CV_MAT_CN(type)), cv::Mat(size, type, hostMem())
126     {
127         assert((type & CV_MAT_DEPTH_MASK) == CV_32F);
128     }
129     MatDynMem(int height, int width, int type)
130         : DynMem(width * height * CV_MAT_CN(type)), cv::Mat(height, width, type, hostMem())
131     {
132         assert((type & CV_MAT_DEPTH_MASK) == CV_32F);
133     }
134     MatDynMem(int ndims, const int *sizes, int type)
135         : DynMem(volume(ndims, sizes) * CV_MAT_CN(type)), cv::Mat(ndims, sizes, type, hostMem())
136     {
137         assert((type & CV_MAT_DEPTH_MASK) == CV_32F);
138     }
139     MatDynMem(std::vector<int> size, int type)
140         : DynMem(std::accumulate(size.begin(), size.end(), 1, std::multiplies<int>()))
141         , cv::Mat(size.size(), size.data(), type, hostMem()) {}
142     MatDynMem(MatDynMem &&other) = default;
143     MatDynMem(const cv::Mat &other)
144         : DynMem(other.total()) , cv::Mat(other) {}
145
146     void operator=(const cv::MatExpr &expr) {
147         static_cast<cv::Mat>(*this) = expr;
148     }
149
150   private:
151     static int volume(int ndims, const int *sizes)
152     {
153         int vol = 1;
154         for (int i = 0; i < ndims; i++)
155             vol *= sizes[i];
156         return vol;
157     }
158
159     using cv::Mat::create;
160 };
161
162 class Mat3d : public MatDynMem
163 {
164 public:
165     Mat3d(uint dim0, cv::Size size) : MatDynMem({{int(dim0), size.height, size.width}}, CV_32F) {}
166
167     cv::Mat plane(uint idx) {
168         assert(dims == 3);
169         assert(int(idx) < size[0]);
170         return cv::Mat(size[1], size[2], cv::Mat::type(), ptr(idx));
171     }
172     const cv::Mat plane(uint idx) const {
173         assert(dims == 3);
174         assert(int(idx) < size[0]);
175         return cv::Mat(size[1], size[2], cv::Mat::type(), const_cast<uchar*>(ptr(idx)));
176     }
177
178 };
179
180 class MatFeats : public Mat3d
181 {
182 public:
183     MatFeats(uint num_features, cv::Size size) : Mat3d(num_features, size) {}
184 };
185 class MatScales : public Mat3d
186 {
187 public:
188     MatScales(uint num_scales, cv::Size size) : Mat3d(num_scales, size) {}
189 };
190
191 class MatScaleFeats : public MatDynMem
192 {
193 public:
194     MatScaleFeats(uint num_scales, uint num_features, cv::Size size)
195         : MatDynMem({{int(num_scales), int(num_features), size.height, size.width}}, CV_32F) {}
196
197     cv::Mat plane(uint scale, uint feature) {
198         assert(dims == 4);
199         assert(int(scale) < size[0]);
200         assert(int(feature) < size[1]);
201         return cv::Mat(size[2], size[3], cv::Mat::type(), ptr(scale, feature));
202     }
203     cv::Mat scale(uint scale) {
204         assert(dims == 4);
205         assert(int(scale) < size[0]);
206         return cv::Mat(3, std::vector<int>({size[1], size[2], size[3]}).data(), cv::Mat::type(), ptr(scale));
207     }
208 };
209
210 #endif // DYNMEM_HPP