GCVL
Multi-platform (Windows, Unix and Mac OS) C++/OpenCL/CUDA library with several Computer Vision algorithms.
src/gcvl/opencl/oclutils.h
Go to the documentation of this file.
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 ***************************************
 All Classes Namespaces Files Functions Variables Defines