Mali OpenCL SDK v1.1.0
 All Classes Files Functions Variables Macros Pages
hello_world_opencl.cpp
Go to the documentation of this file.
1 /*
2  * This confidential and proprietary software may be used only as
3  * authorised by a licensing agreement from ARM Limited
4  * (C) COPYRIGHT 2013 ARM Limited
5  * ALL RIGHTS RESERVED
6  * The entire notice above must be reproduced on all authorised
7  * copies and copies may only be made to the extent permitted
8  * by a licensing agreement from ARM Limited.
9  */
10 
11 #include "common.h"
12 #include "image.h"
13 
14 #include <CL/cl.h>
15 #include <iostream>
16 
17 using namespace std;
18 
25 int main(void)
26 {
27  cl_context context = 0;
28  cl_command_queue commandQueue = 0;
29  cl_program program = 0;
30  cl_device_id device = 0;
31  cl_kernel kernel = 0;
32  int numberOfMemoryObjects = 3;
33  cl_mem memoryObjects[3] = {0, 0, 0};
34  cl_int errorNumber;
35 
36  if (!createContext(&context))
37  {
38  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
39  cerr << "Failed to create an OpenCL context. " << __FILE__ << ":"<< __LINE__ << endl;
40  return 1;
41  }
42 
43  if (!createCommandQueue(context, &commandQueue, &device))
44  {
45  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
46  cerr << "Failed to create the OpenCL command queue. " << __FILE__ << ":"<< __LINE__ << endl;
47  return 1;
48  }
49 
50  if (!createProgram(context, device, "assets/hello_world_opencl.cl", &program))
51  {
52  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
53  cerr << "Failed to create OpenCL program." << __FILE__ << ":"<< __LINE__ << endl;
54  return 1;
55  }
56 
57  kernel = clCreateKernel(program, "hello_world_opencl", &errorNumber);
58  if (!checkSuccess(errorNumber))
59  {
60  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
61  cerr << "Failed to create OpenCL kernel. " << __FILE__ << ":"<< __LINE__ << endl;
62  return 1;
63  }
64 
65  /* [Setup memory] */
66  /* Number of elements in the arrays of input and output data. */
67  cl_int arraySize = 1000000;
68 
69  /* The buffers are the size of the arrays. */
70  size_t bufferSize = arraySize * sizeof(cl_int);
71 
72  /*
73  * Ask the OpenCL implementation to allocate buffers for the data.
74  * We ask the OpenCL implemenation to allocate memory rather than allocating
75  * it on the CPU to avoid having to copy the data later.
76  * The read/write flags relate to accesses to the memory from within the kernel.
77  */
78  bool createMemoryObjectsSuccess = true;
79 
80  memoryObjects[0] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, bufferSize, NULL, &errorNumber);
81  createMemoryObjectsSuccess &= checkSuccess(errorNumber);
82 
83  memoryObjects[1] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, bufferSize, NULL, &errorNumber);
84  createMemoryObjectsSuccess &= checkSuccess(errorNumber);
85 
86  memoryObjects[2] = clCreateBuffer(context, CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, bufferSize, NULL, &errorNumber);
87  createMemoryObjectsSuccess &= checkSuccess(errorNumber);
88 
89  if (!createMemoryObjectsSuccess)
90  {
91  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
92  cerr << "Failed to create OpenCL buffer. " << __FILE__ << ":"<< __LINE__ << endl;
93  return 1;
94  }
95  /* [Setup memory] */
96 
97  /* [Map the buffers to pointers] */
98  /* Map the memory buffers created by the OpenCL implementation to pointers so we can access them on the CPU. */
99  bool mapMemoryObjectsSuccess = true;
100 
101  cl_int* inputA = (cl_int*)clEnqueueMapBuffer(commandQueue, memoryObjects[0], CL_TRUE, CL_MAP_WRITE, 0, bufferSize, 0, NULL, NULL, &errorNumber);
102  mapMemoryObjectsSuccess &= checkSuccess(errorNumber);
103 
104  cl_int* inputB = (cl_int*)clEnqueueMapBuffer(commandQueue, memoryObjects[1], CL_TRUE, CL_MAP_WRITE, 0, bufferSize, 0, NULL, NULL, &errorNumber);
105  mapMemoryObjectsSuccess &= checkSuccess(errorNumber);
106 
107  if (!mapMemoryObjectsSuccess)
108  {
109  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
110  cerr << "Failed to map buffer. " << __FILE__ << ":"<< __LINE__ << endl;
111  return 1;
112  }
113  /* [Map the buffers to pointers] */
114 
115  /* [Initialize the input data] */
116  for (int i = 0; i < arraySize; i++)
117  {
118  inputA[i] = i;
119  inputB[i] = i;
120  }
121  /* [Initialize the input data] */
122 
123  /* [Un-map the buffers] */
124  /*
125  * Unmap the memory objects as we have finished using them from the CPU side.
126  * We unmap the memory because otherwise:
127  * - reads and writes to that memory from inside a kernel on the OpenCL side are undefined.
128  * - the OpenCL implementation cannot free the memory when it is finished.
129  */
130  if (!checkSuccess(clEnqueueUnmapMemObject(commandQueue, memoryObjects[0], inputA, 0, NULL, NULL)))
131  {
132  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
133  cerr << "Unmapping memory objects failed " << __FILE__ << ":"<< __LINE__ << endl;
134  return 1;
135  }
136 
137  if (!checkSuccess(clEnqueueUnmapMemObject(commandQueue, memoryObjects[1], inputB, 0, NULL, NULL)))
138  {
139  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
140  cerr << "Unmapping memory objects failed " << __FILE__ << ":"<< __LINE__ << endl;
141  return 1;
142  }
143  /* [Un-map the buffers] */
144 
145  /* [Set the kernel arguments] */
146  bool setKernelArgumentsSuccess = true;
147  setKernelArgumentsSuccess &= checkSuccess(clSetKernelArg(kernel, 0, sizeof(cl_mem), &memoryObjects[0]));
148  setKernelArgumentsSuccess &= checkSuccess(clSetKernelArg(kernel, 1, sizeof(cl_mem), &memoryObjects[1]));
149  setKernelArgumentsSuccess &= checkSuccess(clSetKernelArg(kernel, 2, sizeof(cl_mem), &memoryObjects[2]));
150 
151  if (!setKernelArgumentsSuccess)
152  {
153  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
154  cerr << "Failed setting OpenCL kernel arguments. " << __FILE__ << ":"<< __LINE__ << endl;
155  return 1;
156  }
157  /* [Set the kernel arguments] */
158 
159  /* An event to associate with the Kernel. Allows us to retrieve profiling information later. */
160  cl_event event = 0;
161 
162  /* [Global work size] */
163  /*
164  * Each instance of our OpenCL kernel operates on a single element of each array so the number of
165  * instances needed is the number of elements in the array.
166  */
167  size_t globalWorksize[1] = {arraySize};
168  /* Enqueue the kernel */
169  if (!checkSuccess(clEnqueueNDRangeKernel(commandQueue, kernel, 1, NULL, globalWorksize, NULL, 0, NULL, &event)))
170  {
171  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
172  cerr << "Failed enqueuing the kernel. " << __FILE__ << ":"<< __LINE__ << endl;
173  return 1;
174  }
175  /* [Global work size] */
176 
177  /* Wait for kernel execution completion. */
178  if (!checkSuccess(clFinish(commandQueue)))
179  {
180  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
181  cerr << "Failed waiting for kernel execution to finish. " << __FILE__ << ":"<< __LINE__ << endl;
182  return 1;
183  }
184 
185  /* Print the profiling information for the event. */
186  printProfilingInfo(event);
187  /* Release the event object. */
188  if (!checkSuccess(clReleaseEvent(event)))
189  {
190  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
191  cerr << "Failed releasing the event object. " << __FILE__ << ":"<< __LINE__ << endl;
192  return 1;
193  }
194 
195  /* Get a pointer to the output data. */
196  cl_int* output = (cl_int*)clEnqueueMapBuffer(commandQueue, memoryObjects[2], CL_TRUE, CL_MAP_READ, 0, bufferSize, 0, NULL, NULL, &errorNumber);
197  if (!checkSuccess(errorNumber))
198  {
199  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
200  cerr << "Failed to map buffer. " << __FILE__ << ":"<< __LINE__ << endl;
201  return 1;
202  }
203 
204  /* [Output the results] */
205  /* Uncomment the following block to print results. */
206  /*
207  for (int i = 0; i < arraySize; i++)
208  {
209  cout << "i = " << i << ", output = " << output[i] << "\n";
210  }
211  */
212  /* [Output the results] */
213 
214  /* Unmap the memory object as we are finished using them from the CPU side. */
215  if (!checkSuccess(clEnqueueUnmapMemObject(commandQueue, memoryObjects[2], output, 0, NULL, NULL)))
216  {
217  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
218  cerr << "Unmapping memory objects failed " << __FILE__ << ":"<< __LINE__ << endl;
219  return 1;
220  }
221 
222  /* Release OpenCL objects. */
223  cleanUpOpenCL(context, commandQueue, program, kernel, memoryObjects, numberOfMemoryObjects);
224 }