FiberVISH 0.2
Fish - The Fiber Bundle API for the Vish Visualization Shell
icl.hpp
1
6#ifndef __FISH_POND_OPENCL_ICL_HPP
7#define __FISH_POND_OPENCL_ICL_HPP
8
9#ifndef HAVE_NO_PRAGMA_ONCE
10#pragma once
11#endif
12
13#include <cstdint>
14#include <memory>
15#include <unordered_map>
16#include <chrono>
17
18#if defined(__APPLE__) || defined(__MACOSX)
20#else
22#endif
23
24
25#include "fish/fiber/FiberHDF5/mtoolslib/MDefs.hpp"
26
27#include "api.h"
28
29namespace icl
30{
31
32 #define checkError(__errorCode, __message) \
33 if(!(__errorCode == CL_SUCCESS)) { \
34 MTOOLS_ERR_OUT( "=============================" ); \
35 MTOOLS_ERR_OUT( "OpenCL Error:\n\t" << __message << ": " << errorString(__errorCode) ); \
36 MTOOLS_ERR_OUT( __FILE__ "#"<< __LINE__ << ":" ); \
37 MTOOLS_ERR_OUT( "=============================" ); \
38 std::exit(EXIT_FAILURE); \
39 }
40
41 #define raiseError(__message) \
42 { \
43 MTOOLS_ERR_OUT( "=============================" ); \
44 MTOOLS_ERR_OUT( "OpenCL Error:\n\t" << __message << "" ); \
45 MTOOLS_ERR_OUT( __FILE__ "#"<< __LINE__ << ":" ); \
46 MTOOLS_ERR_OUT( "=============================" ); \
47 std::exit(EXIT_FAILURE); \
48 }
49
50 MYAPI enum device_type : cl_ulong
51 {
52 CPU = (1 << 1),
53 GPU = (1 << 2),
54 ACL = (1 << 3),
55 ALL = (0xFFFFFFFF)
56 };
57
58 MYAPI enum buffer_flag : cl_ulong
59 {
60 READ_WRITE = (1 << 0),
61 READ = (1 << 1),
62 WRITE = (1 << 2)
63 };
64
65 MYAPI enum print_flag : cl_int
66 {
67 SHORT = 0,
68 LONG = 1
69 };
70
71 MYAPI enum kernel_flag : cl_int
72 {
73 STRING = 0,
74 FILE = 1
75 };
76
77 MYAPI enum time_flag : cl_int
78 {
79 NANO = 0,
80 MILLI = 1,
81 MICRO = 2,
82 SEC = 3
83 };
84
85 MYAPI using NDRange = cl::NDRange;
86 MYAPI static const NDRange NullRange;
87
88 MYAPI const std::string errorString (cl_int err);
89
90 MYAPI class Device
91 {
92
93 class Buffer
94 {
95 friend class Device;
96 cl::Buffer cl_buffer;
97 buffer_flag flag;
98 size_t size;
99
100 public:
101 Buffer(){}
102 Buffer(cl::Buffer b, buffer_flag f, size_t s)
103 : cl_buffer(b), flag(f), size(s){}
104 };
105
106 class Kernel
107 {
108 friend class Device;
109 cl::Kernel cl_kernel;
110
111 public:
112 Kernel(){}
113 Kernel(cl::Kernel k)
114 : cl_kernel(k) {}
115 };
116
117 friend class Platform;
118 cl::Device cl_device;
119 cl::Context cl_context;
120 cl::CommandQueue cl_queue;
121
122 std::string name;
123 std::string vendor;
124 cl_ulong type;
125 cl_ulong max_buffer_size;
126 cl_ulong memory_size;
127 cl_ulong used_memory;
128
131
133 : cl_device(d), cl_context(c), cl_queue(q), used_memory(0)
134 {
135 cl_device.getInfo(CL_DEVICE_NAME, &name);
136 cl_device.getInfo(CL_DEVICE_VENDOR, &vendor);
137 cl_device.getInfo(CL_DEVICE_TYPE, &type);
138 cl_device.getInfo(CL_DEVICE_MAX_MEM_ALLOC_SIZE, &max_buffer_size);
139 cl_device.getInfo(CL_DEVICE_GLOBAL_MEM_SIZE, &memory_size);
140 }
141
142 cl::Program buildProgram(const std::string& file_name, kernel_flag flag);
143 void buildKernel(const std::string& kernel_name, const cl::Program& cl_program);
144
145
146 template <typename T>
147 cl_int setArg(cl::Kernel& cl_kernel, cl_uint pos, const T arg)
148 {
149 return cl_kernel.setArg( pos, arg );
150 }
151
152
153
154 void setArguments(cl::Kernel& cl_kernel, cl_uint pos)
155 {
156 return;
157 }
158
159 template <typename T, typename... Ts>
160 void setArguments(cl::Kernel& cl_kernel, cl_uint pos, const T& arg, const Ts&... arguments)
161 {
162 cl_int err = setArg(cl_kernel, pos, arg);
163
164 checkError(err, "Error setting the kernel argument with index " << pos);
165 setArguments(cl_kernel, pos+1, arguments...);
166 }
167
168 public:
169 void print () const;
170
171 void createBuffer(const std::string& key, buffer_flag flag, size_t size);
172
173 void writeBuffer(const std::string& key, size_t size, const void* source_ptr);
174
175 void readBuffer(const std::string& key, size_t size, void* source_ptr);
176
177 void deleteBuffer(const std::string& key);
178 void deleteBuffer(const std::initializer_list<std::string>& keys);
179
180 void createKernel(const std::string& kernel_name, const std::string& file_name, kernel_flag flag);
181 void createKernel(const std::initializer_list<std::string>& kernel_names, const std::string& file_name, kernel_flag flag);
182
183 void deleteKernel(const std::string& key);
184 void deleteKernel(const std::initializer_list<std::string>& keys);
185
186 template <typename... Ts>
187 void runKernel(const std::string& key, const NDRange& global, const NDRange& local, const Ts&... arguments)
188 {
189 const auto& result = kernel_map.find(key);
190 if (result == kernel_map.end())
191 {
192 raiseError("Kernel \"" << key << "\" not found!!");
193 }
194 else
195 {
196 cl::Kernel cl_kernel((kernel_map[key]).cl_kernel); // making a copy
197 setArguments(cl_kernel, 0, arguments...);
198
199 cl_int err = cl_queue.enqueueNDRangeKernel(cl_kernel, NullRange, global, local);
200
201 checkError(err, "Error running the kernel " << key);
202 //err = cl_queue.finish();
203 //checkError(err, "Error during the finish operation");
204 err = cl_queue.flush();
205 checkError(err, "Error during the flush operation");
206 }
207 }
208
209 void finishKernels(){
210 cl_int err = cl_queue.finish();
211 checkError(err, "Error during the finish operation");
212 }
213
214 };
215
216 template<>
217 cl_int Device::setArg<const char*>(cl::Kernel& cl_kernel, cl_uint pos, const char* key);
218
219 template<>
220 cl_int Device::setArg<std::string>(cl::Kernel& cl_kernel, cl_uint pos, std::string key);
221
222 MYAPI class Platform
223 {
224 private:
225 std::vector<Device> devices;
226
227 Platform();
228 Platform(Platform const&);
229 void operator=(Platform const&);
230 public:
231 static Platform& getInstance() {
232 static Platform instance;
233 return instance;
234 }
235
236 const cl_ulong getNumDevices() const;
237
238 Device& getDevice(uint32_t id);
239
240 Device& getGPU();
241
242 Device& getCPU();
243
244 Device& getGPUPreferred();
245
246 Device& getCPUPreferred();
247
248 std::vector<Device>& getDevices();
249
250 void printDevices(print_flag flag = SHORT) const;
251 };
252
253
254 using namespace std::chrono;
255
256 MYAPI class Timer
257 {
258 private:
259 high_resolution_clock::time_point time;
261 public:
262 Timer() : duration(nanoseconds::zero()){};
263
264 void start(){
265 time = high_resolution_clock::now();
266 }
267
268 void reset()
269 {
270 time = high_resolution_clock::now();
271 duration = nanoseconds::zero();
272 }
273
274 double stop(icl::time_flag time_flag = icl::MILLI)
275 {
276 duration += (high_resolution_clock::now() - time);
277 double value = 0;
278 switch(time_flag) {
279 case icl::NANO:
280 value = nanoseconds(duration).count();
281 break;
282 case icl::MICRO:
283 value = duration_cast<microseconds>(duration).count();
284 break;
285 case icl::MILLI:
286 value = duration_cast<milliseconds>(duration).count();
287 break;
288 case icl::SEC:
289 value = duration_cast<seconds>(duration).count();
290 break;
291 }
292 return value;
293 }
294 };
295}
296#endif
duration< int64_t, nano > nanoseconds
valarray< size_t > size() const
basic_string< char > string
__gnu_cxx::__promote< _Tp >::__type arg(_Tp __x)
iterator end() noexcept
iterator find(const key_type &__x)
C++ bindings for OpenCL 1.0 (rev 48), OpenCL 1.1 (rev 33) and OpenCL 1.2 (rev 15)
Class interface for Buffer Memory Objects.
Definition cl.hpp:3038
CommandQueue interface for cl_command_queue.
Definition cl.hpp:5090
cl_int flush() const
Deprecated APIs for 1.2.
Definition cl.hpp:6145
Deprecated APIs for 1.2.
Definition cl.hpp:2348
Class interface for cl_device_id.
Definition cl.hpp:1908
cl_int getInfo(cl_device_info name, T *param) const
Wrapper for clGetDeviceInfo().
Definition cl.hpp:1955
Class interface for cl_kernel.
Definition cl.hpp:4492
Class interface for specifying NDRange values.
Definition cl.hpp:4383
Program interface that implements cl_program.
Definition cl.hpp:4633
Definition icl.hpp:91
Definition icl.hpp:223
Definition icl.hpp:257
Simplified OpenCL Interface.
Definition icl.cpp:9