root/src/parallelization/hiparsimulator/openclstepper.h @ 133:da36bb3f5bff

Revision 133:da36bb3f5bff, 9.5 KB (checked in by Andreas Schaefer <gentryx@…>, 16 months ago)

fixed OpenCLStepper creation

Line 
1#include <libgeodecomp/config.h>
2#ifdef LIBGEODECOMP_FEATURE_OPENCL
3
4#ifndef _libgeodecomp_parallelization_hiparsimulator_openclstepper_h_
5#define _libgeodecomp_parallelization_hiparsimulator_openclstepper_h_
6
7#ifndef __CL_ENABLE_EXCEPTIONS
8#define __CL_ENABLE_EXCEPTIONS
9#endif
10
11#include <boost/shared_ptr.hpp>
12#include <CL/cl.h>
13
14#include <libgeodecomp/misc/cl.hpp>
15#include <libgeodecomp/parallelization/hiparsimulator/stepper.h>
16
17namespace LibGeoDecomp {
18namespace HiParSimulator {
19
20template<typename CELL_TYPE>
21class OpenCLStepper : public Stepper<CELL_TYPE>
22{
23    friend class OpenCLStepperTest;
24public:
25    const static int DIM = CELL_TYPE::Topology::DIMENSIONS;
26
27    typedef class Stepper<CELL_TYPE> ParentType;
28    typedef typename ParentType::GridType GridType;
29    typedef PartitionManager< 
30        DIM, typename CELL_TYPE::Topology> MyPartitionManager;
31 
32    inline OpenCLStepper(
33        const std::string& cellSourceFile,
34        boost::shared_ptr<MyPartitionManager> _partitionManager,
35        Initializer<CELL_TYPE> *_initializer,
36        const int& platformID=0,
37        const int& deviceID=0) :
38        ParentType(_partitionManager, _initializer)
39    {
40        std::vector<cl::Platform> platforms;
41        cl::Platform::get(&platforms);
42        std::vector<cl::Device> devices;
43        platforms[platformID].getDevices(CL_DEVICE_TYPE_ALL, &devices);
44        cl::Device usedDevice = devices[deviceID];
45        context = cl::Context(devices);
46        cmdQueue = cl::CommandQueue(context, usedDevice);
47
48        std::string clSourceString = 
49"#if defined(cl_khr_fp64)\n"
50"#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"
51"#elif defined(cl_amd_fp64)\n"
52"#pragma OPENCL EXTENSION cl_amd_fp64 : enable\n"
53"#endif\n"
54"\n"
55"#include \"" + cellSourceFile + "\"\n"
56"\n"
57#include <libgeodecomp/parallelization/hiparsimulator/escapedopenclkernel.h>
58            ;
59
60        cl::Program::Sources clSource(
61            1, 
62            std::make_pair(clSourceString.c_str(), 
63                           clSourceString.size()));
64        cl::Program clProgram(context, clSource);
65
66        try {
67            clProgram.build(devices);
68        } catch (...) {
69            // Normally we don't catch exceptions, but in this case
70            // printing the build log (which might get lost otherwise)
71            // is valuable for the user who needs to debug his code.
72            std::cerr << "Build Log: " 
73                      << clProgram.getBuildInfo<CL_PROGRAM_BUILD_LOG>(usedDevice) << "\n";
74            throw;
75        }
76
77        kernel = cl::Kernel(clProgram, "execute");
78
79        // fixme:
80        // curStep = initializer().startStep();
81        // curNanoStep = 0;
82        // initGrids();
83    }
84
85    inline virtual std::pair<int, int> currentStep() const
86    {
87        return std::make_pair(curStep, curNanoStep);
88    }
89
90    inline virtual void update(int nanoSteps) 
91    {
92        // fixme: implement me (later)
93        try {
94            cl::Buffer startCoordsBuffer, endCoordsBuffer;
95       
96            Coord<DIM> c = this->initializer->gridDimensions();
97            int zDim = c.z();
98            int yDim = c.y();
99            int xDim = c.x();
100       
101            int actualX = xDim;
102            int actualY = yDim;
103               
104            std::vector<int> startCoords;
105            std::vector<int> endCoords;
106               
107            genThreadCoords(
108                &startCoords,
109                &endCoords,
110                0,
111                0,
112                0,
113                xDim,
114                yDim,
115                zDim,
116                actualX,
117                actualY,
118                zDim,
119                1);
120
121            startCoordsBuffer = cl::Buffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, startCoords.size()*sizeof(int), &startCoords[0]);
122            endCoordsBuffer = cl::Buffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, endCoords.size()*sizeof(int), &endCoords[0]);
123       
124            cl::NDRange global(actualX, actualY, zDim);
125            //fixme: local range could be chosen dynamically
126            cl::NDRange local(16, 16, 1);
127       
128            cl::KernelFunctor livingKernel = kernel.bind(cmdQueue, global, local);
129            livingKernel(inputDeviceGrid, outputDeviceGrid, zDim, yDim, xDim,
130                         1, 0, 0, 0,
131                         startCoordsBuffer, endCoordsBuffer, actualX, actualY);
132            livingKernel.getError();
133            cmdQueue.finish();
134       
135
136        } catch (cl::Error& err) {
137            std::cerr << "OpenCL error: " << err.what() << ", " << oclStrerror(err.err()) << std::endl;
138            throw err;
139        } catch (...) {
140            throw;
141        }
142    }
143
144    inline virtual const GridType& grid() const
145    {
146        cmdQueue.enqueueReadBuffer(
147            outputDeviceGrid, true, 0, 
148            hostGrid->getDimensions().prod() * sizeof(CELL_TYPE), hostGrid->baseAddress());
149        return *hostGrid;
150    }
151
152private:
153    int curStep;
154    int curNanoStep;
155    boost::shared_ptr<GridType> hostGrid;
156
157    cl::Buffer inputDeviceGrid;
158    cl::Buffer outputDeviceGrid;
159    cl::Context context;
160    cl::CommandQueue cmdQueue;
161    cl::Kernel kernel;
162   
163    inline void genThreadCoords(std::vector<int> *startCoords,
164                         std::vector<int> *endCoords,
165                         const int& offset_x,
166                         const int& offset_y,
167                         const int& offset_z,
168                         const int& active_x,
169                         const int& active_y,
170                         const int& active_z,
171                         const int& actual_x,
172                         const int& actual_y,
173                         const int& actual_z,
174                         const int& planes)
175    {
176      int maxX = active_x;
177      int maxY = active_y;
178      int maxZ = ceil(1.0 * actual_z/planes);
179      int numThreads = actual_x * actual_y * maxZ;
180      startCoords->resize(numThreads);
181      endCoords->resize(numThreads);
182   
183      for (int z = 0; z < maxZ; ++z) {
184        int startZ = offset_z + z * planes;
185        int endZ = std::min(offset_z + active_z, 
186                            startZ + planes);
187       
188        for (int y = 0; y < actual_y; ++y) {
189          for (int x = 0; x < actual_x; ++x) {
190            int threadID = (z * actual_x * actual_y) + (y * actual_x) + x; 
191            int myEndZ = endZ;
192            if (x >= maxX || y >= maxY)
193              myEndZ = startZ;
194               
195            (*startCoords)[threadID] = startZ;
196            (*endCoords)[threadID] = myEndZ;
197          }
198        }
199      }
200    }
201
202    inline void initGrids()
203    {
204        const CoordBox<DIM>& gridBox = 
205            this->partitionManager->ownRegion().boundingBox();
206        hostGrid.reset(new GridType(gridBox, CELL_TYPE()));
207        this->initializer->grid(&*hostGrid);
208       
209        inputDeviceGrid = cl::Buffer(
210            context, 
211            CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, 
212            hostGrid->getDimensions().prod() * sizeof(CELL_TYPE), 
213            hostGrid->baseAddress());
214        std::vector<CELL_TYPE> zeroMem(hostGrid->getDimensions().prod(), 0);
215        outputDeviceGrid = cl::Buffer(
216            context, 
217            CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, 
218            hostGrid->getDimensions().prod() * sizeof(CELL_TYPE), 
219            &zeroMem[0]);
220    }
221
222    inline std::string oclStrerror (int nr) {
223      switch (nr) {
224      case 0:
225        return "CL_SUCCESS";
226      case -1:
227        return "CL_DEVICE_NOT_FOUND";
228      case -2:
229        return "CL_DEVICE_NOT_AVAILABLE";
230      case -3:
231        return "CL_COMPILER_NOT_AVAILABLE";
232      case -4:
233        return "CL_MEM_OBJECT_ALLOCATION_FAILURE";
234      case -5:
235        return "CL_OUT_OF_RESOURCES";
236      case -6:
237        return "CL_OUT_OF_HOST_MEMORY";
238      case -7:
239        return "CL_PROFILING_INFO_NOT_AVAILABLE";
240      case -8:
241        return "CL_MEM_COPY_OVERLAP";
242      case -9:
243        return "CL_IMAGE_FORMAT_MISMATCH";
244      case -10:
245        return "CL_IMAGE_FORMAT_NOT_SUPPORTED";
246      case -11:
247        return "CL_BUILD_PROGRAM_FAILURE";
248      case -12:
249        return "CL_MAP_FAILURE";
250      case -13:
251        return "CL_MISALIGNED_SUB_BUFFER_OFFSET";
252      case -14:
253        return "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST";
254      case -30:
255        return "CL_INVALID_VALUE";
256      case -31:
257        return "CL_INVALID_DEVICE_TYPE";
258      case -32:
259        return "CL_INVALID_PLATFORM";
260      case -33:
261        return "CL_INVALID_DEVICE";
262      case -34:
263        return "CL_INVALID_CONTEXT";
264      case -35:
265        return "CL_INVALID_QUEUE_PROPERTIES";
266      case -36:
267        return "CL_INVALID_COMMAND_QUEUE";
268      case -37:
269        return "CL_INVALID_HOST_PTR";
270      case -38:
271        return "CL_INVALID_MEM_OBJECT";
272      case -39:
273        return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR";
274      case -40:
275        return "CL_INVALID_IMAGE_SIZE";
276      case -41:
277        return "CL_INVALID_SAMPLER";
278      case -42:
279        return "CL_INVALID_BINARY";
280      case -43:
281        return "CL_INVALID_BUILD_OPTIONS";
282      case -44:
283        return "CL_INVALID_PROGRAM";
284      case -45:
285        return "CL_INVALID_PROGRAM_EXECUTABLE";
286      case -46:
287        return "CL_INVALID_KERNEL_NAME";
288      case -47:
289        return "CL_INVALID_KERNEL_DEFINITION";
290      case -48:
291        return "CL_INVALID_KERNEL";
292      case -49:
293        return "CL_INVALID_ARG_INDEX";
294      case -50:
295        return "CL_INVALID_ARG_VALUE";
296      case -51:
297        return "CL_INVALID_ARG_SIZE";
298      case -52:
299        return "CL_INVALID_KERNEL_ARGS";
300      case -53:
301        return "CL_INVALID_WORK_DIMENSION";
302      case -54:
303        return "CL_INVALID_WORK_GROUP_SIZE";
304      case -55:
305        return "CL_INVALID_WORK_ITEM_SIZE";
306      case -56:
307        return "CL_INVALID_GLOBAL_OFFSET";
308      case -57:
309        return "CL_INVALID_EVENT_WAIT_LIST";
310      case -58:
311        return "CL_INVALID_EVENT";
312      case -59:
313        return "CL_INVALID_OPERATION";
314      case -60:
315        return "CL_INVALID_GL_OBJECT";
316      case -61:
317        return "CL_INVALID_BUFFER_SIZE";
318      case -62:
319        return "CL_INVALID_MIP_LEVEL";
320      case -63:
321        return "CL_INVALID_GLOBAL_WORK_SIZE";
322      case -64:
323        return "CL_INVALID_PROPERTY";
324      }
325      return "nothing found";
326    }
327};
328
329}
330}
331
332#endif
333#endif
Note: See TracBrowser for help on using the browser.