MultiThreadSIFT.cpp
Go to the documentation of this file.
00001 
00002 //    File:        MultiThreadSIFT.cpp
00003 //    Author:      Changchang Wu
00004 //    Description : An example to show how to use SiftGPU in multi-threading
00005 //                  with each thread using different GPU device.
00006 //                  The same idea also applies to SiftMatchGPU.
00007 //
00008 //
00009 //    Copyright (c) 2007 University of North Carolina at Chapel Hill
00010 //    All Rights Reserved
00011 //
00012 //    Permission to use, copy, modify and distribute this software and its
00013 //    documentation for educational, research and non-profit purposes, without
00014 //    fee, and without a written agreement is hereby granted, provided that the
00015 //    above copyright notice and the following paragraph appear in all copies.
00016 //    
00017 //    The University of North Carolina at Chapel Hill make no representations
00018 //    about the suitability of this software for any purpose. It is provided
00019 //    'as is' without express or implied warranty. 
00020 //
00021 //    Please send BUG REPORTS to ccwu@cs.unc.edu
00022 //
00024 
00025 
00026 #include <stdlib.h>
00027 #include <vector>
00028 #include <iostream>
00029 using std::vector;
00030 using std::iostream;
00031 #include <time.h>
00032 
00033 
00034 #ifdef _WIN32
00035     #include <windows.h>
00036     //define this to get dll import definition for win32
00037     #define SIFTGPU_DLL
00038     #ifdef _DEBUG 
00039         #pragma comment(lib, "../../lib/siftgpu_d.lib")
00040     #else
00041         #pragma comment(lib, "../../lib/siftgpu.lib")
00042     #endif
00043     #define thread_t HANDLE
00044 #else
00045     #include <stdio.h>
00046     #include <pthread.h>
00047     #define thread_t pthread_t
00048     pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
00049 #endif
00050 
00051 
00052 #include "../SiftGPU/SiftGPU.h"
00053 
00054 class ScopedMutex
00055 {
00056 #ifdef _WIN32
00057 private:
00058         HANDLE hmutex;
00059 public:
00060         ScopedMutex(const char* name) {
00061                 hmutex = CreateMutex(NULL, FALSE, name);
00062                 WaitForSingleObject(hmutex, INFINITE);
00063         }
00064         ~ScopedMutex()
00065         {
00066                 ReleaseMutex(hmutex);
00067                 CloseHandle(hmutex);
00068         }
00069 #else
00070 public:
00071         ScopedMutex(const char* name) {
00072         pthread_mutex_lock(&global_mutex);
00073         }
00074         ~ScopedMutex()
00075         {
00076                 pthread_mutex_unlock(&global_mutex);
00077         }
00078 #endif
00079 };
00080 
00081 
00082 
00083 class MultiThreadSIFT
00084 {
00085 protected:
00086     SiftGPU*    _sift;
00087     const void *  _thread_param;
00088     int         _device_id;
00089 private:
00090     void Initialize(int device_id)
00091     {
00092         ScopedMutex mutex("siftgpu_initialize");
00093         printf("#%d: Initialize MultiThreadSIFT...", device_id);
00094         InitializeSIFT();
00095         printf("done\n");
00096 
00097         //The initialization part should be protected by a mutex in
00098         //single-process-multi-thread mode. For now many parameters 
00099         //are still global static variables. 
00100     }
00101 public:
00102     MultiThreadSIFT(int device_id = 0, const void* thread_param = NULL)
00103     {
00104         _thread_param = thread_param;
00105         _device_id = device_id;
00106     }
00107     virtual ~MultiThreadSIFT()
00108     {
00109         if(_sift) delete _sift;
00110     }
00111 
00112     thread_t RunThread()
00113     {
00114 #ifdef _WIN32
00115         return CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RunMultiThreadSIFT, this, 0, 0);
00116 #else
00117         thread_t threadid;
00118         pthread_create(&threadid, NULL, RunMultiThreadSIFT, this);
00119         return threadid;
00120 #endif
00121     }
00122 #ifdef _WIN32
00123     static DWORD
00124 #else
00125     static void*
00126 #endif
00127     RunMultiThreadSIFT(void* mts)
00128     {
00129         MultiThreadSIFT* mtsift = (MultiThreadSIFT*) mts;
00130         mtsift->Initialize(mtsift->_device_id); 
00131         mtsift->RunTask();
00132         return 0;
00133     }
00134 public:
00135     //Two Functions to overload for specific task
00136     virtual void RunTask()
00137     {
00138 
00139     }
00140     //set parameters and initizlze SIFT
00141     virtual void InitializeSIFT()
00142     {
00144             char device[2] = {'0' + _device_id, '\0'}; //works for 0-9...use sprintf if you have more than 10
00145         char * argv[] = {"-fo", "-1",  "-v", "0", "-cuda", device};
00146         //-nogl was previously required, but now default 
00147         int argc = sizeof(argv)/sizeof(char*);
00148 
00150         _sift = new SiftGPU;
00151         _sift->ParseParam(argc, argv);
00152 
00153         //create an OpenGL context for computation, and SiftGPU will be initialized automatically 
00154         if(_sift->CreateContextGL() != SiftGPU::SIFTGPU_FULL_SUPPORTED)         exit(0);
00155     }
00156 };
00157 
00158 
00159 //Multi-threading demo. 
00160 //Each thread will load a file, and repeat the processing 100 times.
00161 
00162 class MultiThreadDemo: public MultiThreadSIFT
00163 {
00164 public:
00165     MultiThreadDemo(int deviceid, const char* filename):  MultiThreadSIFT(deviceid, filename)
00166     {
00167     }
00168     virtual void RunTask()
00169     {
00170         printf("#%d, running task\n", _device_id);
00171         time_t t1, t2;
00172         t1 = time(NULL);
00173         for(int i = 0; i < 100; ++i) _sift->RunSIFT();
00174         t2 = time(NULL); 
00175         printf("#%d: %dhz\n", _device_id, int(100/(t2-t1)));
00176     }
00177     virtual void InitializeSIFT()
00178     {
00179         MultiThreadSIFT::InitializeSIFT();
00180         const char* filename = (const char*) _thread_param;
00181         _sift->RunSIFT(filename);
00182 
00184         //WARNING: the image loader (DeviL) used by SiftGPU is not thread-safe. 
00185         //This demo will put the file loading part in InitializeSIFT, which
00186         //is protected by a mutex. In your multi-thread application, you should
00187         //load the image data outside SiftGPU, and specify the memory data to 
00188         //SiftGPU directly. 
00190     }
00191 };
00192 
00193 //Multi-process demo
00194 //Each process will repeat the processing of a file for 100 times.
00195 class MultiProcessDemo: public MultiThreadSIFT
00196 {
00197 public:
00198     MultiProcessDemo(int deviceid, const char* filename):  MultiThreadSIFT(deviceid, filename)
00199     {
00200     }   
00201     virtual void RunTask()
00202     {
00203         char* filename = (char*) _thread_param;
00204         time_t t1, t2;
00205         t1 = time(NULL);
00206         for(int i = 0; i < 100; ++i) _sift->RunSIFT(filename);
00207         t2 = time(NULL); 
00208         printf("Speed on device %d : %dhz\n", _device_id, int(100/(t2-t1)));
00209     }
00210     virtual void InitializeSIFT()
00211     {
00212                 //Although the multi-process demo here uses CUDA, 
00213                 //if multiple GPUs are mapped to multiple monitors/displayes
00214                 //it is possible to use OpenGL (not CUDA)for this. 
00215         //Also, the mutex protection is not necessary
00216             char device[2] = {'0' + _device_id, '\0'}; //works for 0-9...use sprintf if you have more than 10
00217         char * argv[] = {"-fo", "-1",  "-v", "0", "-cuda", device};
00218         int argc = sizeof(argv)/sizeof(char*);
00219 
00221                 //create two server with differ socket ports
00222         _sift = CreateRemoteSiftGPU(7777 + _device_id, NULL);
00223         _sift->ParseParam(argc, argv);
00224 
00225         //create an OpenGL context for computation, and SiftGPU will be initialized automatically 
00226         if(_sift->CreateContextGL() != SiftGPU::SIFTGPU_FULL_SUPPORTED)         exit(0);
00227     }
00228 };
00229 
00230 
00231 int main()
00232 {
00233     //NOTE that SiftGPU must be compiled with CUDA for this demo
00234     MultiThreadDemo thread1(0, "../data/640-1.jpg");
00235     MultiThreadDemo thread2(1, "../data/800-1.jpg");
00236 
00237 
00238         //Use MultiProcessDemo for multi-process mode
00239     //MultiProcessDemo thread1(0, "../data/640-1.jpg");
00240     //MultiProcessDemo thread2(1, "../data/800-1.jpg");
00241 
00242     printf("Starting two threads...\n");
00243     thread_t t1 = thread1.RunThread();
00244     thread_t t2 = thread2.RunThread();
00245 
00246 #ifdef _WIN32
00247     HANDLE handles[2] = {t1, t2};
00248     WaitForMultipleObjects(2, handles, TRUE, INFINITE); 
00250     CloseHandle(t1); 
00251     CloseHandle(t2);
00252 #else   
00253     pthread_join(t1, NULL);
00254     pthread_join(t2, NULL);
00255 #endif
00256     return 1;
00257 }
00258 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


rgbd_registration
Author(s): Ross Kidson
autogenerated on Thu May 23 2013 15:36:53