|
ViennaCL - The Vienna Computing Library
1.1.2
|
00001 /* ======================================================================= 00002 Copyright (c) 2010, Institute for Microelectronics, TU Vienna. 00003 http://www.iue.tuwien.ac.at 00004 ----------------- 00005 ViennaCL - The Vienna Computing Library 00006 ----------------- 00007 00008 authors: Karl Rupp rupp@iue.tuwien.ac.at 00009 Florian Rudolf flo.rudy+viennacl@gmail.com 00010 Josef Weinbub weinbub@iue.tuwien.ac.at 00011 00012 license: MIT (X11), see file LICENSE in the ViennaCL base directory 00013 ======================================================================= */ 00014 00015 #ifndef _VIENNACL_ENQUEUE_HPP_ 00016 #define _VIENNACL_ENQUEUE_HPP_ 00017 00022 #ifdef __APPLE__ 00023 #include <OpenCL/cl.h> 00024 #else 00025 #include <CL/cl.h> 00026 #endif 00027 00028 #include "viennacl/ocl/kernel.hpp" 00029 #include "viennacl/ocl/command_queue.hpp" 00030 00031 namespace viennacl 00032 { 00033 namespace ocl 00034 { 00035 00037 template <typename KernelType> 00038 void enqueue(KernelType & k, viennacl::ocl::command_queue const & queue) 00039 { 00040 // 1D kernel: 00041 if (k.local_work_size(1) == 0) 00042 { 00043 #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_KERNEL) 00044 std::cout << "ViennaCL: Starting 1D-kernel '" << k.name() << "'..." << std::endl; 00045 std::cout << "ViennaCL: Global work size: '" << k.global_work_size() << "'..." << std::endl; 00046 std::cout << "ViennaCL: Local work size: '" << k.local_work_size() << "'..." << std::endl; 00047 #endif 00048 00049 size_t tmp_global = k.global_work_size(); 00050 size_t tmp_local = k.local_work_size(); 00051 00052 cl_int err; 00053 if (tmp_global == 1 && tmp_local == 1) 00054 err = clEnqueueTask(queue.handle(), k.handle(), 0, NULL, NULL); 00055 else 00056 err = clEnqueueNDRangeKernel(queue.handle(), k.handle(), 1, NULL, &tmp_global, &tmp_local, 0, NULL, NULL); 00057 00058 if (err != CL_SUCCESS) //if not successful, try to start with smaller work size 00059 { 00060 //std::cout << "FAIL: " << std::endl; exit(0); 00061 while (err != CL_SUCCESS && tmp_local > 1) 00062 { 00063 //std::cout << "Flushing queue, then enqueuing again with half the size..." << std::endl; 00064 //std::cout << "Error code: " << err << std::endl; 00065 00066 tmp_global /= 2; 00067 tmp_local /= 2; 00068 00069 #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_KERNEL) 00070 std::cout << "ViennaCL: Kernel start failed for '" << k.name() << "'." << std::endl; 00071 std::cout << "ViennaCL: Global work size: '" << tmp_global << "'..." << std::endl; 00072 std::cout << "ViennaCL: Local work size: '" << tmp_local << "'..." << std::endl; 00073 #endif 00074 00075 queue.finish(); 00076 err = clEnqueueNDRangeKernel(queue.handle(), k.handle(), 1, NULL, &tmp_global, &tmp_local, 0, NULL, NULL); 00077 } 00078 00079 if (err != CL_SUCCESS) 00080 { 00081 //could not start kernel with any parameters 00082 std::cerr << "ViennaCL: FATAL ERROR: Kernel start failed for '" << k.name() << "'." << std::endl; 00083 std::cerr << "ViennaCL: Smaller work sizes could not solve the problem. " << std::endl; 00084 VIENNACL_ERR_CHECK(err); 00085 } 00086 else 00087 { 00088 //remember parameters: 00089 k.local_work_size(0, tmp_local); 00090 k.global_work_size(0, tmp_global); 00091 #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_KERNEL) 00092 std::cout << "ViennaCL: Kernel '" << k.name() << "' now uses global work size " << tmp_global << " and local work size " << tmp_local << "." << std::endl; 00093 #endif 00094 } 00095 } 00096 } 00097 else //2D kernel 00098 { 00099 #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_KERNEL) 00100 std::cout << "ViennaCL: Starting 2D-kernel '" << k.name() << "'..." << std::endl; 00101 std::cout << "ViennaCL: Global work size: '" << k.global_work_size(0) << ", " << k.global_work_size(1) << "'..." << std::endl; 00102 std::cout << "ViennaCL: Local work size: '" << k.local_work_size(0) << ", " << k.local_work_size(1) << "'..." << std::endl; 00103 #endif 00104 00105 size_t tmp_global[2]; 00106 tmp_global[0] = k.global_work_size(0); 00107 tmp_global[1] = k.global_work_size(1); 00108 00109 size_t tmp_local[2]; 00110 tmp_local[0] = k.local_work_size(0); 00111 tmp_local[1] = k.local_work_size(1); 00112 00113 cl_int err = clEnqueueNDRangeKernel(queue.handle(), k.handle(), 2, NULL, tmp_global, tmp_local, 0, NULL, NULL); 00114 00115 if (err != CL_SUCCESS) 00116 { 00117 //could not start kernel with any parameters 00118 std::cerr << "ViennaCL: FATAL ERROR: Kernel start failed for '" << k.name() << "'." << std::endl; 00119 VIENNACL_ERR_CHECK(err); 00120 } 00121 00122 } 00123 00124 #if defined(VIENNACL_DEBUG_ALL) || defined(VIENNACL_DEBUG_KERNEL) 00125 queue.finish(); 00126 std::cout << "ViennaCL: Kernel " << k.name() << " finished!" << std::endl; 00127 #endif 00128 } //enqueue() 00129 00130 00132 template <typename KernelType> 00133 void enqueue(KernelType & k) 00134 { 00135 enqueue(k, viennacl::ocl::current_context().get_queue()); 00136 } 00137 } // namespace ocl 00138 } // namespace viennacl 00139 #endif
1.7.6.1