added HAVE_CUDA, HAVE_TBB handling into multi_gpu sample
authorAlexey Spizhevoy <no@email>
Thu, 27 Jan 2011 13:48:33 +0000 (13:48 +0000)
committerAlexey Spizhevoy <no@email>
Thu, 27 Jan 2011 13:48:33 +0000 (13:48 +0000)
samples/gpu/multi_gpu.cpp

index 262f6e0..c569875 100644 (file)
 \r
 #include <iostream>\r
 #include <cvconfig.h>\r
+#include "opencv2/core/core.hpp"\r
 #include <opencv2/gpu/gpu.hpp>\r
-#include <opencv2/highgui/highgui.hpp>\r
 \r
-#ifdef HAVE_CUDA\r
-#include <cuda_runtime.h>\r
-#endif\r
-\r
-using namespace std;\r
-using namespace cv;\r
+#if !defined(HAVE_CUDA) || !defined(HAVE_TBB)\r
 \r
 int main()\r
 {\r
-    bool can_run = true;\r
-\r
 #if !defined(HAVE_CUDA)\r
     cout << "CUDA support is required (CMake key 'WITH_CUDA' must be true).\n";\r
-    can_run = false;\r
 #endif\r
 \r
 #if !defined(HAVE_TBB)\r
     cout << "TBB support is required (CMake key 'WITH_TBB' must be true).\n";\r
-    can_run = false;\r
 #endif\r
 \r
-    if (!can_run)\r
+    return 0;\r
+}\r
+\r
+#else\r
+\r
+#include <cuda.h>\r
+#include <cuda_runtime.h>\r
+#include "opencv2/core/internal.hpp" // For TBB wrappers\r
+\r
+using namespace std;\r
+using namespace cv;\r
+using namespace cv::gpu;\r
+\r
+\r
+void cuSafeCall(int code);\r
+struct Worker { void operator()(int device_id) const; };\r
+void destroy();\r
+\r
+\r
+// Each GPU is associated with its own context\r
+CUcontext contexts[2];\r
+\r
+// Auxiliary variable, stores previusly used context\r
+CUcontext prev_context;\r
+\r
+\r
+int main()\r
+{\r
+    if (getCudaEnabledDeviceCount() < 2)\r
+    {\r
+        cout << "Two or more GPUs are required\n";\r
         return -1;\r
+    }\r
+\r
+    // Save the default context\r
+    cuSafeCall(cuCtxAttach(&contexts[0], 0));\r
+    cuSafeCall(cuCtxDetach(contexts[0]));\r
+\r
+    // Create new context for the second GPU\r
+    CUdevice device;\r
+    cuSafeCall(cuDeviceGet(&device, 1));\r
+    cuSafeCall(cuCtxCreate(&contexts[1], 0, device));\r
+\r
+    // Restore the first GPU context\r
+    cuSafeCall(cuCtxPopCurrent(&prev_context));\r
+\r
+    // Run \r
+    int devices[] = {0, 1};\r
+    parallel_do(devices, devices + 2, Worker());\r
+\r
+    // Destroy context of the second GPU\r
+    destroy();\r
 \r
     return 0;\r
-}
\ No newline at end of file
+}\r
+\r
+\r
+void Worker::operator()(int device_id) const\r
+{\r
+    cout << device_id << endl;\r
+}\r
+\r
+\r
+void cuSafeCall(int code)\r
+{\r
+    if (code != CUDA_SUCCESS) \r
+    {\r
+        cout << "CUDA driver API error: code " << code \r
+            << ", file " << __FILE__ \r
+            << ", line " << __LINE__ << endl;\r
+        destroy();\r
+        exit(-1);\r
+    }\r
+}\r
+\r
+\r
+void destroy() \r
+{\r
+    cuCtxDestroy(contexts[1]);\r
+}\r
+\r
+#endif
\ No newline at end of file