|
GCVL
Multi-platform (Windows, Unix and Mac OS) C++/OpenCL/CUDA library with several Computer Vision algorithms.
|
00001 /* 00002 * 00003 * GPGPU Computer Vision Library (GCVL) 00004 * 00005 * Copyright (c) Nicolas Bigaouette 2011 <nbigaouette@gmail.com> 00006 * Copyright (c) Luis Omar Alvarez Mures 2015 <omar.alvarez@udc.es> 00007 * Copyright (c) Emilio Padron Gonzalez 2015 <emilioj@gmail.com> 00008 * 00009 * All rights reserved. 00010 * 00011 * This library is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public 00013 * License as published by the Free Software Foundation; either 00014 * version 3 of the License, or (at your option) any later version. 00015 * 00016 * This library is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 * General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public 00022 * License along with this library. 00023 * 00024 */ 00025 00026 #pragma once 00027 00028 #include <string> 00029 #include <list> 00030 #include <map> 00031 #include <climits> 00032 #include <stdint.h> 00033 00034 #ifdef __APPLE__ 00035 #include "OpenCL/opencl.h" 00036 #else 00037 #include "CL/cl.h" 00038 #endif 00039 00040 #ifndef std_cout 00041 #define std_cout std::cout 00042 #include <iostream> 00043 #include <fstream> 00044 #include <fstream> 00045 #endif // #ifndef std_cout 00046 00047 const std::string OPENCL_PLATFORMS_NVIDIA("nvidia"); 00048 const std::string OPENCL_PLATFORMS_AMD("amd"); 00049 const std::string OPENCL_PLATFORMS_INTEL("intel"); 00050 const std::string OPENCL_PLATFORMS_APPLE("apple"); 00051 00052 // ***************************************************************************** 00053 #define OpenCL_Test_Success(err, fct_name) \ 00054 if ((err) != CL_SUCCESS) \ 00055 { \ 00056 std_cout \ 00057 << "ERROR calling " << fct_name << "() (" \ 00058 << __FILE__ << " line " << __LINE__ << "): " \ 00059 << OpenCL_Error_to_String(err) << "\n" << std::flush; \ 00060 abort(); \ 00061 } 00062 00063 // ***************************************************************************** 00064 #define OpenCL_Release_Kernel(err, opencl_kernel) \ 00065 { \ 00066 if ((opencl_kernel)) err = clReleaseKernel((opencl_kernel)); \ 00067 OpenCL_Test_Success(err, "clReleaseKernel"); \ 00068 } 00069 00070 // ***************************************************************************** 00071 #define OpenCL_Release_Program(err, opencl_program) \ 00072 { \ 00073 if ((opencl_program)) err = clReleaseProgram((opencl_program)); \ 00074 OpenCL_Test_Success(err, "clReleaseProgram"); \ 00075 } 00076 00077 // ***************************************************************************** 00078 #define OpenCL_Release_CommandQueue(err, opencl_cqueue) \ 00079 { \ 00080 if ((opencl_cqueue)) err = clReleaseCommandQueue((opencl_cqueue));\ 00081 OpenCL_Test_Success(err, "clReleaseCommandQueue"); \ 00082 } 00083 00084 // ***************************************************************************** 00085 #define OpenCL_Release_Memory(err, opencl_array) \ 00086 { \ 00087 if ((opencl_array)) err = clReleaseMemObject((opencl_array)); \ 00088 OpenCL_Test_Success(err, "clReleaseMemObject"); \ 00089 } 00090 00091 // ***************************************************************************** 00092 #define OpenCL_Release_Context(err, opencl_context) \ 00093 { \ 00094 if ((opencl_context)) err = clReleaseContext((opencl_context)); \ 00095 OpenCL_Test_Success(err, "clReleaseContext"); \ 00096 } 00097 00098 class OpenCL_platform; 00099 class OpenCL_platforms_list; 00100 class OpenCL_device; 00101 class OpenCL_devices_list; 00102 class OpenCL_Kernel; 00103 00104 // ***************************************************************************** 00105 // Nvidia extensions. On non-nvidia, needs to define those. 00106 #ifndef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV 00107 #define CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV 0x4000 00108 #endif 00109 #ifndef CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV 00110 #define CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV 0x4001 00111 #endif 00112 #ifndef CL_DEVICE_REGISTERS_PER_BLOCK_NV 00113 #define CL_DEVICE_REGISTERS_PER_BLOCK_NV 0x4002 00114 #endif 00115 #ifndef CL_DEVICE_WARP_SIZE_NV 00116 #define CL_DEVICE_WARP_SIZE_NV 0x4003 00117 #endif 00118 #ifndef CL_DEVICE_GPU_OVERLAP_NV 00119 #define CL_DEVICE_GPU_OVERLAP_NV 0x4004 00120 #endif 00121 #ifndef CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV 00122 #define CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV 0x4005 00123 #endif 00124 #ifndef CL_DEVICE_INTEGRATED_MEMORY_NV 00125 #define CL_DEVICE_INTEGRATED_MEMORY_NV 0x4006 00126 #endif 00127 00128 // ***************************************************************************** 00129 std::string OpenCL_Error_to_String(cl_int error); 00130 00131 // ***************************************************************************** 00132 bool Verify_if_Device_is_Used(const int device_id, const int platform_id_offset, 00133 const std::string &platform_name, const std::string &device_name); 00134 00135 // ***************************************************************************** 00136 char *read_opencl_kernel(const std::string filename, int *length); 00137 00138 // ***************************************************************************** 00139 class OpenCL_device 00140 { 00141 private: 00142 bool object_is_initialized; 00143 int device_id; 00144 cl_device_id device; 00145 cl_context context; 00146 bool device_is_gpu; 00147 bool device_is_in_use; 00148 00149 // OpenCL device's information. 00150 // See http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/clGetDeviceInfo.html 00151 cl_uint address_bits; 00152 cl_bool available; 00153 cl_bool compiler_available; 00154 cl_device_fp_config double_fp_config; 00155 cl_bool endian_little; 00156 cl_bool error_correction_support; 00157 cl_device_exec_capabilities execution_capabilities; 00158 cl_ulong global_mem_cache_size; 00159 cl_device_mem_cache_type global_mem_cache_type; 00160 cl_uint global_mem_cacheline_size; 00161 cl_ulong global_mem_size; 00162 cl_device_fp_config half_fp_config; 00163 cl_bool image_support; 00164 size_t image2d_max_height; 00165 size_t image2d_max_width; 00166 size_t image3d_max_depth; 00167 size_t image3d_max_height; 00168 size_t image3d_max_width; 00169 cl_ulong local_mem_size; 00170 cl_device_local_mem_type local_mem_type; 00171 cl_uint max_clock_frequency; 00172 cl_uint max_compute_units; 00173 cl_uint max_constant_args; 00174 cl_ulong max_constant_buffer_size; 00175 cl_ulong max_mem_alloc_size; 00176 size_t max_parameter_size; 00177 cl_uint max_read_image_args; 00178 cl_uint max_samplers; 00179 size_t max_work_group_size; 00180 cl_uint max_work_item_dimensions; 00181 size_t max_work_item_sizes[3]; 00182 cl_uint max_write_image_args; 00183 cl_uint mem_base_addr_align; 00184 cl_uint min_data_type_align_size; 00185 cl_platform_id platform; 00186 cl_uint preferred_vector_width_char; 00187 cl_uint preferred_vector_width_short; 00188 cl_uint preferred_vector_width_int; 00189 cl_uint preferred_vector_width_long; 00190 cl_uint preferred_vector_width_float; 00191 cl_uint preferred_vector_width_double; 00192 size_t profiling_timer_resolution; 00193 cl_command_queue_properties queue_properties; 00194 cl_device_fp_config single_fp_config; 00195 cl_device_type type; 00196 cl_uint vendor_id; 00197 00198 std::string extensions; 00199 std::string name; 00200 std::string profile; 00201 std::string vendor; 00202 std::string version; 00203 std::string driver_version; 00204 std::string type_string; 00205 std::string queue_properties_string; 00206 std::string single_fp_config_string; 00207 00208 // Nvidia specific extensions 00209 // http://developer.download.nvidia.com/compute/cuda/3_2_prod/toolkit/docs/OpenCL_Extensions/cl_nv_device_attribute_query.txt 00210 bool is_nvidia; 00211 cl_uint nvidia_device_compute_capability_major; 00212 cl_uint nvidia_device_compute_capability_minor; 00213 cl_uint nvidia_device_registers_per_block; 00214 cl_uint nvidia_device_warp_size; 00215 cl_bool nvidia_device_gpu_overlap; 00216 cl_bool nvidia_device_kernel_exec_timeout; 00217 cl_bool nvidia_device_integrated_memory; 00218 00219 // A lock can be acquired on the device only if another program 00220 // did not acquired one before. If the program detects that the device 00221 // was is used by another process, it won't try to lock or unlock the device. 00222 bool is_lockable; 00223 bool file_locked; 00224 int lock_file; 00225 00226 public: 00227 00228 const OpenCL_platform *parent_platform; 00229 00230 OpenCL_device(); 00231 ~OpenCL_device(); 00232 void Destructor(); 00234 00237 const OpenCL_platform * Get_Parent_Platform() { return parent_platform; } 00239 00242 std::string Get_Name() const { return name; } 00244 00247 cl_uint Get_Compute_Units() const { return max_compute_units; } 00249 00252 int Get_ID() const { return device_id; } 00254 00257 cl_device_id & Get_Device() { return device; } 00259 00262 cl_context & Get_Context() { return context; } 00264 00267 bool Is_In_Use() { return device_is_in_use; } 00269 00272 bool Is_Lockable() { return is_lockable; } 00274 void Set_Lockable(const bool _is_lockable) { is_lockable = _is_lockable; } 00275 00276 void Set_Information(const int _id, cl_device_id _device, const int platform_id_offset, 00277 const std::string &platform_name, const bool _device_is_gpu, 00278 const OpenCL_platform * const _parent_platform); 00279 00280 cl_int Set_Context(); 00281 void Print() const; 00282 void Lock(); 00283 void Unlock(); 00284 bool operator<(const OpenCL_device &b) const; 00285 }; 00286 00287 // ***************************************************************************** 00288 class OpenCL_devices_list 00289 { 00290 private: 00291 bool is_initialized; 00292 const OpenCL_platform *platform; 00293 std::list<OpenCL_device> device_list; 00294 cl_uint nb_cpu; 00295 cl_uint nb_gpu; 00296 int err; 00297 bool are_all_devices_in_use; 00298 00299 public: 00300 00301 OpenCL_device *preferred_device; 00302 00303 OpenCL_devices_list(); 00304 ~OpenCL_devices_list(); 00305 00306 void Set_Preferred_OpenCL(const int _preferred_device = -1); 00307 OpenCL_device & Preferred_OpenCL(); 00309 00312 cl_device_id & Preferred_OpenCL_Device() { return Preferred_OpenCL().Get_Device(); } 00314 00317 cl_context & Preferred_OpenCL_Device_Context() { return Preferred_OpenCL().Get_Context(); } 00319 00322 int nb_devices() { return nb_cpu + nb_gpu; } 00323 void Print() const; 00324 void Initialize(const OpenCL_platform &_platform, 00325 const std::string &preferred_platform); 00326 00327 }; 00328 00329 // ***************************************************************************** 00330 class OpenCL_platform 00331 { 00332 private: 00333 cl_platform_id id; 00334 std::string profile; 00335 std::string version; 00336 std::string name; 00337 std::string vendor; 00338 std::string extensions; 00339 std::string key; 00340 OpenCL_platforms_list *platform_list; 00341 int id_offset; 00342 public: 00343 OpenCL_devices_list devices_list; 00344 OpenCL_platform(); 00345 00346 void Initialize(std::string _key, int id_offset, cl_platform_id _id, 00347 OpenCL_platforms_list *_platform_list, const std::string preferred_platform); 00349 00352 OpenCL_device & Preferred_OpenCL() { return devices_list.Preferred_OpenCL(); } 00354 00357 cl_device_id & Preferred_OpenCL_Device() { return devices_list.Preferred_OpenCL_Device(); } 00359 00362 cl_context & Preferred_OpenCL_Device_Context() { return devices_list.Preferred_OpenCL_Device_Context(); } 00364 00367 OpenCL_platforms_list * Platform_List() const { return platform_list; } 00368 void Print_Preferred() const; 00370 00373 std::string Key() const { return key; } 00375 00378 std::string const Name() const { return name; } 00380 00383 cl_platform_id Id() const { return id; } 00385 00388 int Id_Offset() const { return id_offset; } 00389 void Lock_Best_Device(); 00390 void Print() const; 00391 }; 00392 00393 // ***************************************************************************** 00394 class OpenCL_platforms_list 00395 { 00396 private: 00397 std::map<std::string,OpenCL_platform> platforms; 00398 std::string preferred_platform; 00399 bool use_locking; 00400 public: 00401 void Initialize(const std::string &_preferred_platform, const bool _use_locking = true); 00402 void Print() const; 00403 void Print_Preferred() const; 00405 00408 std::string Get_Running_Platform() { return preferred_platform; } 00410 00413 bool Use_Locking() const { return use_locking; } 00414 00415 OpenCL_platform & operator[](const std::string key); 00416 void Set_Preferred_OpenCL(const int _preferred_device = -1); 00417 }; 00418 00419 // ************************************************************** 00420 class OpenCL_Kernel 00421 { 00422 public: 00423 00424 OpenCL_Kernel(); 00425 OpenCL_Kernel(std::string _filename, const cl_context &_context, 00426 const cl_device_id &_device_id); 00427 ~OpenCL_Kernel(); 00428 void Initialize(std::string _filename, const cl_context &_context, 00429 const cl_device_id &_device_id); 00430 00431 void Build(std::string _kernel_name); 00432 00433 // By default global_y is one, local_x is MAX_WORK_SIZE and local_y is one. 00434 void Compute_Work_Size(size_t _global_x, size_t _global_y, size_t _local_x, size_t _local_y); 00435 00436 const cl_kernel& Get_Kernel() const; 00437 00438 size_t *Get_Global_Work_Size() const; 00439 size_t *Get_Local_Work_Size() const; 00440 00441 int Get_Dimension() const; 00442 void Append_Compiler_Option(const std::string option); 00443 00444 void Launch(const cl_command_queue &command_queue); 00445 00446 static int Get_Multiple(int n, int base); 00447 00448 private: 00449 00450 std::string filename; 00451 cl_context context; 00452 cl_device_id device_id; 00453 00454 std::string compiler_options; 00455 std::string kernel_name; 00456 00457 int dimension; 00458 int p; 00459 int q; 00460 00461 cl_program program; 00462 00463 cl_kernel kernel; 00464 size_t *global_work_size; 00465 size_t *local_work_size; 00466 00467 // Debugging variables 00468 cl_int err; 00469 cl_event event; 00470 00471 void Load_Program_From_File(); 00472 00473 void Build_Executable(const bool verbose = true); 00474 }; 00475 00476 00477 // ***************************************************************************** 00478 template <class T> 00479 class OpenCL_Array 00480 { 00481 private: 00482 bool array_is_padded; // Will the array need to be padded for checksumming? 00483 int N; // Number of elements in array 00484 size_t sizeof_element; // Size of each array elements 00485 uint64_t new_array_size_bytes; // Size (bytes) of new padded array 00486 T *host_array; // Pointer to start of host array, INCLUDIǸG padding 00487 uint64_t nb_1024bits_blocks; // Number of 1024 bits blocks in padded array 00488 std::string platform; // OpenCL platform 00489 cl_context context; // OpenCL context 00490 cl_command_queue command_queue; // OpenCL command queue 00491 cl_device_id device; // OpenCL device 00492 cl_int err; // Error code 00493 00494 uint8_t host_checksum[64]; // SHA512 checksum on host memory (512 bits) 00495 uint8_t device_checksum[64]; // SHA512 checksum on device memory (512 bits) 00496 static const int buff_size_checksum = sizeof(uint8_t) * 64; 00497 00498 OpenCL_Kernel kernel_checksum; // Kernel for checksum calculation 00499 00500 // Allocated memory on device 00501 cl_mem device_array; // Memory of device 00502 cl_mem cl_array_size_bit; 00503 cl_mem cl_sha512sum; 00504 00505 public: 00506 OpenCL_Array(); 00507 void Initialize(int _N, const size_t _sizeof_element, 00508 T *&host_array, 00509 const cl_context &_context, cl_mem_flags flags, 00510 std::string _platform, 00511 const cl_command_queue &_command_queue, 00512 const cl_device_id &_device, 00513 const bool _checksum_array); 00514 void Release_Memory(); 00515 void Host_to_Device(); 00516 void Device_to_Host(); 00517 std::string Host_Checksum(); 00518 std::string Device_Checksum(); 00519 void Validate_Data(); 00520 00522 00525 inline cl_mem * Get_Device_Array() { return &device_array; } 00527 00530 inline T * Get_Host_Pointer() { return host_array; } 00531 void Set_as_Kernel_Argument(cl_kernel &kernel, const int order); 00532 }; 00533 00534 // ***************************************************************************** 00535 template <class T> 00536 class OpenCL_Data 00537 { 00538 private: 00539 T data; 00540 cl_int err; 00541 public: 00542 OpenCL_Data(); 00543 void Initialize(T _data); 00544 void Set_as_Kernel_Argument(cl_kernel &kernel, const int order); 00545 }; 00546 00547 // ********** End of file ***************************************