root / rgbdslam / external / siftgpu / src / TestWin / MultiThreadSIFT.cpp @ 9240aaa3
History | View | Annotate | Download (7.68 KB)
1 |
////////////////////////////////////////////////////////////////////////////
|
---|---|
2 |
// File: MultiThreadSIFT.cpp
|
3 |
// Author: Changchang Wu
|
4 |
// Description : An example to show how to use SiftGPU in multi-threading
|
5 |
// with each thread using different GPU device.
|
6 |
// The same idea also applies to SiftMatchGPU.
|
7 |
//
|
8 |
//
|
9 |
// Copyright (c) 2007 University of North Carolina at Chapel Hill
|
10 |
// All Rights Reserved
|
11 |
//
|
12 |
// Permission to use, copy, modify and distribute this software and its
|
13 |
// documentation for educational, research and non-profit purposes, without
|
14 |
// fee, and without a written agreement is hereby granted, provided that the
|
15 |
// above copyright notice and the following paragraph appear in all copies.
|
16 |
//
|
17 |
// The University of North Carolina at Chapel Hill make no representations
|
18 |
// about the suitability of this software for any purpose. It is provided
|
19 |
// 'as is' without express or implied warranty.
|
20 |
//
|
21 |
// Please send BUG REPORTS to ccwu@cs.unc.edu
|
22 |
//
|
23 |
////////////////////////////////////////////////////////////////////////////
|
24 |
|
25 |
|
26 |
#include <stdlib.h> |
27 |
#include <vector> |
28 |
#include <iostream> |
29 |
using std::vector;
|
30 |
using std::iostream;
|
31 |
#include <time.h> |
32 |
|
33 |
|
34 |
#ifdef _WIN32
|
35 |
#include <windows.h> |
36 |
//define this to get dll import definition for win32
|
37 |
#define SIFTGPU_DLL
|
38 |
#ifdef _DEBUG
|
39 |
#pragma comment(lib, "../../lib/siftgpu_d.lib") |
40 |
#else
|
41 |
#pragma comment(lib, "../../lib/siftgpu.lib") |
42 |
#endif
|
43 |
#define thread_t HANDLE
|
44 |
#else
|
45 |
#include <stdio.h> |
46 |
#include <pthread.h> |
47 |
#define thread_t pthread_t
|
48 |
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER; |
49 |
#endif
|
50 |
|
51 |
|
52 |
#include "../SiftGPU/SiftGPU.h" |
53 |
|
54 |
class ScopedMutex |
55 |
{ |
56 |
#ifdef _WIN32
|
57 |
private:
|
58 |
HANDLE hmutex; |
59 |
public:
|
60 |
ScopedMutex(const char* name) { |
61 |
hmutex = CreateMutex(NULL, FALSE, name);
|
62 |
WaitForSingleObject(hmutex, INFINITE); |
63 |
} |
64 |
~ScopedMutex() |
65 |
{ |
66 |
ReleaseMutex(hmutex); |
67 |
CloseHandle(hmutex); |
68 |
} |
69 |
#else
|
70 |
public:
|
71 |
ScopedMutex(const char* name) { |
72 |
pthread_mutex_lock(&global_mutex); |
73 |
} |
74 |
~ScopedMutex() |
75 |
{ |
76 |
pthread_mutex_unlock(&global_mutex); |
77 |
} |
78 |
#endif
|
79 |
}; |
80 |
|
81 |
|
82 |
|
83 |
class MultiThreadSIFT |
84 |
{ |
85 |
protected:
|
86 |
SiftGPU* _sift; |
87 |
const void * _thread_param; |
88 |
int _device_id;
|
89 |
private:
|
90 |
void Initialize(int device_id) |
91 |
{ |
92 |
ScopedMutex mutex("siftgpu_initialize");
|
93 |
printf("#%d: Initialize MultiThreadSIFT...", device_id);
|
94 |
InitializeSIFT(); |
95 |
printf("done\n");
|
96 |
|
97 |
//The initialization part should be protected by a mutex in
|
98 |
//single-process-multi-thread mode. For now many parameters
|
99 |
//are still global static variables.
|
100 |
} |
101 |
public:
|
102 |
MultiThreadSIFT(int device_id = 0, const void* thread_param = NULL) |
103 |
{ |
104 |
_thread_param = thread_param; |
105 |
_device_id = device_id; |
106 |
} |
107 |
virtual ~MultiThreadSIFT()
|
108 |
{ |
109 |
if(_sift) delete _sift; |
110 |
} |
111 |
|
112 |
thread_t RunThread() |
113 |
{ |
114 |
#ifdef _WIN32
|
115 |
return CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RunMultiThreadSIFT, this, 0, 0); |
116 |
#else
|
117 |
thread_t threadid; |
118 |
pthread_create(&threadid, NULL, RunMultiThreadSIFT, this); |
119 |
return threadid;
|
120 |
#endif
|
121 |
} |
122 |
#ifdef _WIN32
|
123 |
static DWORD
|
124 |
#else
|
125 |
static void* |
126 |
#endif
|
127 |
RunMultiThreadSIFT(void* mts)
|
128 |
{ |
129 |
MultiThreadSIFT* mtsift = (MultiThreadSIFT*) mts; |
130 |
mtsift->Initialize(mtsift->_device_id); |
131 |
mtsift->RunTask(); |
132 |
return 0; |
133 |
} |
134 |
public:
|
135 |
//Two Functions to overload for specific task
|
136 |
virtual void RunTask() |
137 |
{ |
138 |
|
139 |
} |
140 |
//set parameters and initizlze SIFT
|
141 |
virtual void InitializeSIFT() |
142 |
{ |
143 |
////////////////////////////
|
144 |
char device[2] = {'0' + _device_id, '\0'}; //works for 0-9...use sprintf if you have more than 10 |
145 |
char * argv[] = {"-fo", "-1", "-v", "0", "-cuda", device}; |
146 |
//-nogl was previously required, but now default
|
147 |
int argc = sizeof(argv)/sizeof(char*); |
148 |
|
149 |
/////////////////////////////////////
|
150 |
_sift = new SiftGPU;
|
151 |
_sift->ParseParam(argc, argv); |
152 |
|
153 |
//create an OpenGL context for computation, and SiftGPU will be initialized automatically
|
154 |
if(_sift->CreateContextGL() != SiftGPU::SIFTGPU_FULL_SUPPORTED) exit(0); |
155 |
} |
156 |
}; |
157 |
|
158 |
|
159 |
//Multi-threading demo.
|
160 |
//Each thread will load a file, and repeat the processing 100 times.
|
161 |
|
162 |
class MultiThreadDemo: public MultiThreadSIFT |
163 |
{ |
164 |
public:
|
165 |
MultiThreadDemo(int deviceid, const char* filename): MultiThreadSIFT(deviceid, filename) |
166 |
{ |
167 |
} |
168 |
virtual void RunTask() |
169 |
{ |
170 |
printf("#%d, running task\n", _device_id);
|
171 |
time_t t1, t2; |
172 |
t1 = time(NULL);
|
173 |
for(int i = 0; i < 100; ++i) _sift->RunSIFT(); |
174 |
t2 = time(NULL);
|
175 |
printf("#%d: %dhz\n", _device_id, int(100/(t2-t1))); |
176 |
} |
177 |
virtual void InitializeSIFT() |
178 |
{ |
179 |
MultiThreadSIFT::InitializeSIFT(); |
180 |
const char* filename = (const char*) _thread_param; |
181 |
_sift->RunSIFT(filename); |
182 |
|
183 |
//////////////////////////////////////////////////////////////////////
|
184 |
//WARNING: the image loader (DeviL) used by SiftGPU is not thread-safe.
|
185 |
//This demo will put the file loading part in InitializeSIFT, which
|
186 |
//is protected by a mutex. In your multi-thread application, you should
|
187 |
//load the image data outside SiftGPU, and specify the memory data to
|
188 |
//SiftGPU directly.
|
189 |
/////////////////////////////////////////////////////////////////////
|
190 |
} |
191 |
}; |
192 |
|
193 |
//Multi-process demo
|
194 |
//Each process will repeat the processing of a file for 100 times.
|
195 |
class MultiProcessDemo: public MultiThreadSIFT |
196 |
{ |
197 |
public:
|
198 |
MultiProcessDemo(int deviceid, const char* filename): MultiThreadSIFT(deviceid, filename) |
199 |
{ |
200 |
} |
201 |
virtual void RunTask() |
202 |
{ |
203 |
char* filename = (char*) _thread_param; |
204 |
time_t t1, t2; |
205 |
t1 = time(NULL);
|
206 |
for(int i = 0; i < 100; ++i) _sift->RunSIFT(filename); |
207 |
t2 = time(NULL);
|
208 |
printf("Speed on device %d : %dhz\n", _device_id, int(100/(t2-t1))); |
209 |
} |
210 |
virtual void InitializeSIFT() |
211 |
{ |
212 |
//Although the multi-process demo here uses CUDA,
|
213 |
//if multiple GPUs are mapped to multiple monitors/displayes
|
214 |
//it is possible to use OpenGL (not CUDA)for this.
|
215 |
//Also, the mutex protection is not necessary
|
216 |
char device[2] = {'0' + _device_id, '\0'}; //works for 0-9...use sprintf if you have more than 10 |
217 |
char * argv[] = {"-fo", "-1", "-v", "0", "-cuda", device}; |
218 |
int argc = sizeof(argv)/sizeof(char*); |
219 |
|
220 |
/////////////////////////////////////
|
221 |
//create two server with differ socket ports
|
222 |
_sift = CreateRemoteSiftGPU(7777 + _device_id, NULL); |
223 |
_sift->ParseParam(argc, argv); |
224 |
|
225 |
//create an OpenGL context for computation, and SiftGPU will be initialized automatically
|
226 |
if(_sift->CreateContextGL() != SiftGPU::SIFTGPU_FULL_SUPPORTED) exit(0); |
227 |
} |
228 |
}; |
229 |
|
230 |
|
231 |
int main()
|
232 |
{ |
233 |
//NOTE that SiftGPU must be compiled with CUDA for this demo
|
234 |
MultiThreadDemo thread1(0, "../data/640-1.jpg"); |
235 |
MultiThreadDemo thread2(1, "../data/800-1.jpg"); |
236 |
|
237 |
|
238 |
//Use MultiProcessDemo for multi-process mode
|
239 |
//MultiProcessDemo thread1(0, "../data/640-1.jpg");
|
240 |
//MultiProcessDemo thread2(1, "../data/800-1.jpg");
|
241 |
|
242 |
printf("Starting two threads...\n");
|
243 |
thread_t t1 = thread1.RunThread(); |
244 |
thread_t t2 = thread2.RunThread(); |
245 |
|
246 |
#ifdef _WIN32
|
247 |
HANDLE handles[2] = {t1, t2};
|
248 |
WaitForMultipleObjects(2, handles, TRUE, INFINITE);
|
249 |
////////////////////////////////////////////////////////////////
|
250 |
CloseHandle(t1); |
251 |
CloseHandle(t2); |
252 |
#else
|
253 |
pthread_join(t1, NULL);
|
254 |
pthread_join(t2, NULL);
|
255 |
#endif
|
256 |
return 1; |
257 |
} |
258 |
|