Initial public release.
[OpenCLIPER] / include / OpenCLIPER / CLapp.hpp
1 /* Copyright (C) 2018 Federico Simmross Wattenberg,
2  *                    Manuel Rodríguez Cayetano,
3  *                    Javier Royuela del Val,
4  *                    Elena Martín González,
5  *                    Elisa Moya Sáez,
6  *                    Marcos Martín Fernández and
7  *                    Carlos Alberola López
8  *
9  * This file is part of OpenCLIPER.
10  *
11  * OpenCLIPER is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; version 3 of the License.
14  *
15  * OpenCLIPER is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with OpenCLIPER; If not, see <http://www.gnu.org/licenses/>.
22  *
23  *
24  *  Contact:
25  *
26  *  Federico Simmross Wattenberg
27  *  E.T.S.I. Telecomunicación
28  *  Universidad de Valladolid
29  *  Paseo de Belén 15
30  *  47011 Valladolid, Spain.
31  *  fedsim@tel.uva.es
32  */
33 #ifndef __OpenCLIPER
34 #define __OpenCLIPER
35
36 #define CL_HPP_ENABLE_EXCEPTIONS
37 #define CL_HPP_TARGET_OPENCL_VERSION 120
38 #define CL_HPP_MINIMUM_OPENCL_VERSION 120
39
40 #if defined(__APPLE__) || defined(__MACOSX)
41 #include<OpenCL/cl.hpp>
42 #else
43 #include<CL/cl2.hpp>
44 #endif
45
46 #include<vector>
47 #include<map>
48 // For gethostname POSIX function
49 #include<stdio.h>
50 #include <stdlib.h>
51 #include <unistd.h>
52 #include <limits.h>
53
54 #include<OpenCLIPER/OpenCLIPERDataModelCommonDefs.hpp>
55 #include<LPISupport/Utils.hpp>
56 #include<LPISupport/InfoItems.hpp>
57 #include<OpenCLIPER/Process.hpp>
58
59 // cl2.hpp includes the | operator but not &
60 // We need it to test for supported command queue properties
61 inline cl::QueueProperties operator&(cl::QueueProperties lhs, cl::QueueProperties rhs) {
62     return static_cast<cl::QueueProperties>(static_cast<cl_command_queue_properties>(lhs) & static_cast<cl_command_queue_properties>(rhs));
63 }
64
65 namespace OpenCLIPER {
66 class Data;
67 class Process;
68
69 /// Data type for a list of OpenCL kernels
70 typedef std::map<std::string,cl::Kernel> kernelListT;
71
72 /**
73  * @brief Class representing an application with an OpenCL device bound
74  *
75  * This class stores:
76  * * infomation about available and selected devices
77  * * a list of Process subclasses objects (representing algorithms to be executed on selected device) 
78  * * a list of Data subclasses objects (used as input and/or output data for Process subclasses objects).
79  */
80 class CLapp: public std::enable_shared_from_this<CLapp>{
81 public:
82
83     /// Enumerated type with the device type options
84     enum DeviceType {
85             DEVICE_TYPE_ANY=CL_DEVICE_TYPE_ALL, ///< any device is valid CPU or GPU
86             DEVICE_TYPE_CPU=CL_DEVICE_TYPE_CPU, ///< only CPU devices are valid
87             DEVICE_TYPE_GPU=CL_DEVICE_TYPE_GPU ///< only GPU devices are valid
88     };
89
90     /// Struct with options for selection of OpenCL platform
91     struct PlatformTraits {
92         /// platform name
93         std::string                  name;
94         /// platform vendor
95         std::string                  vendor;
96         /// platform version
97         std::string                  version;
98         /// platform required extensions
99         std::vector<std::string> extensions;
100     };
101
102     /// Struct with options for selection of OpenCL device
103     struct DeviceTraits {
104         /// type of device (CPU, GPU, etc.)
105         DeviceType                      type;
106         /// device name
107         std::string                     name;
108         /// device vendor
109         std::string                     vendor;
110         /// device version
111         std::string                     version;
112         /// device required extensions
113         std::vector<std::string>        extensions;
114         /// device queue properties
115         cl::QueueProperties             queueProperties;
116
117         /**
118          * @brief Default constructor for struct fields initialization.
119          * 
120          */
121         DeviceTraits(DeviceType t=DEVICE_TYPE_ANY,cl::QueueProperties p=cl::QueueProperties::None): 
122             type(t), queueProperties(p) {}
123     };
124
125     /// @brief Default constructor (empty).
126     CLapp() {}
127     CLapp(const PlatformTraits& platformTraits,const DeviceTraits& deviceTraits);
128     ~CLapp();
129
130     static const char* getOpenCLErrorCodeStr(const cl_int err);
131     /**
132      * @brief Sets error text explantation from error code (integer)
133      * @param[in] err error code
134      * @param[out] errStr text message for the error code
135      */
136     void                setOpenCLErrorCodeStr(const cl_int err,const char* errStr) { errStrings[err]=errStr; }
137     static int  dumpInfo();
138     void                init();
139     void                init(const PlatformTraits& platformTraits, const DeviceTraits& deviceTraits);
140     void                loadKernels(const std::string&               filename, const char* compilerOptionsArg=nullptr);
141     void                loadKernels(const std::vector<std::string> & filenames,const char* compilerOptionsArg=nullptr);
142
143     /**
144      * @brief Gets OpenCL context
145      * @return reference to the OpenCL context
146      */
147     const cl::Context&  getContext() const {return context;}
148
149     /**
150      * @brief Gets OpenCL device from list of devices
151      * @param[in] i position of device in the list of devices
152      * @return reference to selected device
153      */
154     const cl::Device&   getDevice(const size_t i=0) const {return devices[i];}
155
156     /**
157      * @brief Gets OpenCL command queue from list of command queues
158      * @param[in] i position of queue in the list of queues
159      * @return reference to selected queue
160      */
161     cl::CommandQueue&   getCommandQueue(const size_t i=0) {return commandQueues[i];}
162
163     /**
164      * @brief Gets OpenCL program from list of programs
165      * @param[in] i position of program in the list of programs
166      * @return reference to selected program
167      */
168     const cl::Program&  getProgram(const size_t i=0) const {return programs[i];}
169
170     /**
171      * @brief Gets kernel (type cl::Kernel) from list of kernels
172      * @param[in] i index of the kernel in the kernels list
173      * @return reference to selected kernel
174      */
175     cl::Kernel&         getKernel(const size_t i=0) {kernelListT::iterator j(kernels.begin()); std::advance(j,i); return j->second;}    // Warning: no bounds checking!
176
177     /**
178      * @brief Gets kernel (type cl::Kernel) from name
179      * @param[in] name name of the kernel
180      * @return reference to selected kernel
181      */
182     cl::Kernel&         getKernel(const char* name) {return getKernel(std::string(name));}
183     cl::Kernel&         getKernel(const std::string& name);
184     static      cl_uint roundUp(cl_uint numToRound, cl_uint baseNumber);
185     ProcessHandle       addProcess(Process*& pProcess);
186     void                    checkProcessHandle(ProcessHandle handle, string specificMessage);
187     void                        delProcess(ProcessHandle handle);
188     std::shared_ptr<Process> getProcess (ProcessHandle handle);
189     DataHandle          addData(Data*& pData, SyncSource hostDeviceSync = SYNCSOURCEDEFAULT);
190     DataHandle      addData(shared_ptr<Data> pData, SyncSource hostDeviceSync = SYNCSOURCEDEFAULT);
191     void                    checkDataHandle(DataHandle handle, string specificMessage);
192     void                        delData(DataHandle handle);
193     std::shared_ptr<Data>       getData (DataHandle handle);
194     void                    host2Device(DataHandle handle, SyncSource host2DeviceSyncSource = SYNCSOURCEDEFAULT);
195     void                    device2Host(DataHandle handle, SyncSource device2HostSyncSource);
196     std::string getDeviceTypeAsString(size_t i=0);
197     LPISupport::InfoItems getHWSWInfo(size_t i=0);
198     std::string getDeviceName(size_t i=0);
199     std::string getDeviceVendor(size_t i=0);
200     cl::NDRange getMaxLocalWorkItemSizes(cl::NDRange globalSizes);
201
202     cl::Buffer* getDeviceBuffer(DataHandle handle, dimIndexType NDArrayIndex) ;
203     cl::Buffer* getDeviceBuffer(DataHandle handle);
204     cl::Image* getDeviceImage(DataHandle handle, dimIndexType NDArrayIndex);
205     void* getHostBuffer(DataHandle handle, dimIndexType NDArrayIndex);
206     void* getHostImage(DataHandle handle, dimIndexType NDArrayIndex);
207
208 private:
209     /// OpenCL platform
210     cl::Platform                        platform;
211     /// OpenCL context
212     cl::Context                 context;
213     /// List of OpenCL devices
214     std::vector<cl::Device>             devices;
215     /// List of OpenCL command queues
216     std::vector<cl::CommandQueue>       commandQueues;
217     /// List of programs
218     std::vector<cl::Program>    programs;
219     /// List of kernels
220     kernelListT                 kernels;
221     /// String error
222     std::string                 errStr;
223     /// Map with process handles as keys and smart shared pointers to processes as values
224     std::map<ProcessHandle, std::shared_ptr<Process>>   processMap;
225     /// Map with process handles as keys and smart shared pointers to Data objects as values
226     std::map<DataHandle, std::shared_ptr<Data>>         dataMap;
227     /// Current valid value for process keys (initially not valid)
228     ProcessHandle                       nextProcessKey = FIRSTVALIDPROCESSHANDLE;
229     /// Current valid value for data keys (initially not valid)
230     DataHandle                  nextDataKey = FIRSTVALIDDATAHANDLE;
231     static std::map<const cl_int,const char*>   errStrings;
232 };
233
234 } //namespace OpenCLIPER
235 #endif //__OpenCLIPER