Statistics
| Branch: | Revision:

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