MatManager.cu
3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <pthread.h>
#include <semaphore.h>
#include <opencv2/opencv.hpp>
#include "MatManager.hpp"
using namespace cv;
using namespace cv::gpu;
namespace br { namespace cuda {
MatManager::MatManager(int num) {
_numMats = num;
// initialize the an array of Mats
_mats = (uint8_t**)malloc(num * sizeof(uint8_t*));
_matTaken = (bool*)malloc(num * sizeof(bool));
_matsDimension = (int*)malloc(num * sizeof(int));
for (int i=0; i < num; i++) {
cudaMalloc(&_mats[i], 1 * sizeof(uint8_t));
// initialize matTaken
_matTaken[i] = false;
// initialize all mat dimensions to be 1
_matsDimension[i] = 1;
}
// initialize the locks
_matTakenLock = new pthread_mutex_t;
pthread_mutex_init(_matTakenLock, NULL);
_matsDimensionLock = new pthread_mutex_t;
pthread_mutex_init(_matsDimensionLock, NULL);
// initialize the semaphore
_matSemaphore = new sem_t;
sem_init(_matSemaphore, 0, _numMats);
}
MatManager::matindex MatManager::reserve(Mat &mat) {
int reservedMatIndex = 0;
sem_wait(_matSemaphore);
pthread_mutex_lock(_matTakenLock);
int i;
for (i=0; i < _numMats; i++) {
if ( !_matTaken[i] ) {
_matTaken[i] = true;
reservedMatIndex = i;
break;
}
}
if (i == _numMats) {
std::cout << "Cannot reserve a mat. Not enough GpuMat resourses\n" << std::endl << std::flush;
}
pthread_mutex_unlock(_matTakenLock);
// reallocate if size does not match
pthread_mutex_lock(_matsDimensionLock);
if (_matsDimension[reservedMatIndex] != mat.rows * mat.cols) {
cudaFree(_mats[reservedMatIndex]); // free the previous memory first
cudaMalloc(&_mats[reservedMatIndex], mat.rows * mat.cols * sizeof(uint8_t));
// change the dimension of that matrix
_matsDimension[reservedMatIndex] = mat.rows * mat.cols;
}
pthread_mutex_unlock(_matsDimensionLock);
return reservedMatIndex;
}
void MatManager::upload(MatManager::matindex reservedMatIndex, Mat& mat) {
// copy the content of the Mat to GPU
uint8_t* reservedMat = _mats[reservedMatIndex];
cudaMemcpy(reservedMat, mat.ptr<uint8_t>(), mat.rows * mat.cols, cudaMemcpyHostToDevice);
}
void MatManager::download(MatManager::matindex reservedMatIndex, Mat& dstMat) {
// copy the mat data back
int dimension = dstMat.rows * dstMat.cols;
uint8_t* reservedMat = _mats[reservedMatIndex];
cudaMemcpy(dstMat.ptr<uint8_t>(), reservedMat, dimension, cudaMemcpyDeviceToHost);
}
void MatManager::release(MatManager::matindex reservedMatIndex) {
uint8_t* reservedMat = _mats[reservedMatIndex];
pthread_mutex_lock(_matTakenLock);
bool foundMatch = false;
for (int i=0; i < _numMats; i++) {
if (reservedMat == _mats[i]) {
_matTaken[i] = false;
foundMatch = true;
}
}
pthread_mutex_unlock(_matTakenLock);
// return unconditionally if we didn't find a match
if (!foundMatch) {
std::cout << "Reservedmat is not in the _mats array" << std::endl << std::flush;
return;
}
sem_post(_matSemaphore);
}
MatManager::~MatManager() {
// assume a single thread is destroying the manager
// TODO(colin): add the destroy code
//std::cout << "Start to destroy.." << std::endl << std::flush;
}
uint8_t* MatManager::get_mat_pointer_from_index(MatManager::matindex matIndex) {
return _mats[matIndex];
}
}}