source: CIVL/examples/translation/openclversion2.14/square.cvl@ 5693398

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since 5693398 was 5693398, checked in by Jacob Trieu <fuufusuu@…>, 12 years ago

reduce example

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@1344 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 7.7 KB
Line 
1//Forget the program
2
3#include "cl.cvl"
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <civlc.h>
8
9$input int NUM_DEVICES;
10$input int MAX_NUM_DEVICES;
11$assume 0 < NUM_DEVICES && NUM_DEVICES < MAX_NUM_DEVICES;
12
13$input int DATA_SIZE;
14$input int MAX_DATA_SIZE;
15$assume 0 < DATA_SIZE && DATA_SIZE < MAX_NUM_DEVICES;
16
17$input int LOCAL;
18$input int MAX_LOCAL;
19$assume 0 < LOCAL && LOCAL < MAX_LOCAL;
20//this args struct will hold all the parameters of for the kernel function
21typedef struct
22{
23 //Variables for kernels
24 /*
25 float * input;
26 float * output;
27 */
28 void * input;
29 void * output;
30 int count;
31
32}args;
33
34/*
35 args * argument - Takes in the struct, which is changed for every program using a different kernel
36*/
37cl_kernel clCreateKernel(args * argument, char function[])
38{
39 cl_kernel kernel;
40 kernel.arguments = argument;
41 kernel.method = function;
42
43 return kernel;
44}
45
46/*
47 This is the kernel that processes compute with
48 int workgroup - Gives the workgroup that a particular process came from, made by clEnqueueNDRangeKernel
49 int global_id - Gives the global_id that a particular process has, given by workfunc
50 int local_id - Gives the local_id that a particular process has, given by workfunc
51 float* input - Kernel argument
52 float* output - Kernel argument
53 int count - Kernel argument
54*/
55void square(int workgroup, int global_id, int local_id, float* input, float* output, int count)
56{
57 //int i = get_global_id(0);
58 int i = global_id;
59 if (i < count)
60 {
61 output[i] = input[i] * input[i];
62 //printf("output[%d] is %d\n", i, output[i]);
63 }
64}
65/*
66 workfunc assigns local and global ids, before calling the kernel.
67 Note: The function should be identical in all transformations except the calling of the kernel, which means that it cannot be in openCLshared.cvl
68 size_t local - The size of the workgroups, used to calculate blocks
69 size_t global - The total amount of work to be done
70 cl_kernel param - Holds the data for local_id, global_id, and the workgroup
71 Use the print statement to get a better idea of what it means to split workgroups, local_ids, and global_ids
72*/
73void workfunc(size_t local, size_t global, cl_kernel param)
74{
75 $proc procs[local];
76 for(int i = local * param.workgroup; i < local * param.workgroup + local; i++)
77 {
78 param.local_id = i % local;
79 param.global_id = i;
80 printf("My workgroup id is %d, my global id is %d, my local id is %d\n", param.workgroup, param.global_id, param.local_id);
81 procs[param.local_id] = $spawn square(param.workgroup, param.global_id, param.local_id, ((args*)param.arguments)->input, ((args*)param.arguments)->output, ((args*)param.arguments)->count);
82 }
83 for(int j = 0; j < local; j++)
84 {
85 $wait(procs[j]);
86 }
87}
88
89/*
90 Splits up and spawns processes based on global and local, using block
91 TODO: remove cl_command_queue completely and put into a "just in case" file, currently not needed
92 cl_command_queue commands - Holds a queue of the order that devices are to be executed
93 cl_kernel kernel - Holds all the arguments for the kernel, as well as local_id, global_id, and the workgroup
94 size_t global - The total amount of work to be done
95 size_t local - Number to split into workgroups by
96*/
97int clEnqueueNDRangeKernel(cl_kernel kernel, size_t global, size_t local)
98{
99
100 $assert(global % local == 0);
101 int numworkgroups = global/local;
102 cl_kernel param[numworkgroups];
103 $proc procs[numworkgroups];
104 //consider $parfor
105
106 /*
107 $domain(1) dom = {0 .. numworkgroups - 1};
108
109 $for(int i: dom)
110 {
111 param[i] = kernel;
112 param[i].workgroup = i;
113 }
114 $parfor(int i: dom)
115 {
116 workfunc(local, global, param[i]);
117 }
118 */
119
120 for(int i = 0; i < global/local; i++)
121 {
122 param[i] = kernel;
123 param[i].workgroup = i;
124 procs[i] = $spawn workfunc(local, global, param[i]);
125 }
126
127 //this part here is the new clFinish(commands);
128 for(int i = 0; i < global/local; i++)
129 {
130 $wait(procs[i]);
131 }
132
133 return CL_SUCCESS;
134
135}
136
137
138int main(int argc, char** argv)
139{
140 //Make function pointers for every method
141 void (*squarePtr) (int, int, int, float *, float *, int);
142 squarePtr = &square;
143
144 args * arguments;
145 arguments = (args*)malloc(sizeof(args));
146
147 float data[DATA_SIZE]; // original data set given to device
148 float results[DATA_SIZE]; // results returned from device
149 unsigned int correct; // number of correct results returned
150
151 size_t global; // global domain size for our calculation
152 size_t local; // local domain size for our calculation
153
154 cl_device_id device_id; // compute device id
155 cl_context context; // compute context
156 cl_command_queue commands; // compute command queue
157 //cl_program program; // compute program
158 cl_kernel kernel; // compute kernel
159 int err;
160
161 float * input; // device memory used for the input array
162 float * output; // device memory used for the output array
163
164 //Puts in data for input
165 unsigned int count = DATA_SIZE;
166 for(int i = 0; i < count; i++)
167 {
168 data[i] = i;
169 }
170
171
172 //clCreateProgram is far different from the real version, this just stores parameters for the kernel
173 //In order to make this clear, it is clCreateProgram and not something like clCreateProgramFromSource, which actually exists in openCL code
174 //program = clCreateProgram(arguments);
175
176 kernel = clCreateKernel(arguments, "square");
177
178 //replaces clCreateBuffer
179 input = (float *) malloc(sizeof(float) * count);
180 output = (float *) malloc(sizeof(float) * count);
181
182
183 //replaces clEnqueueWriteBuffer, puts data into the input to be put into the kernel arguments
184 memcpy(input, data, sizeof(float) * count);
185
186 /*
187 err = 0;
188 err = clSetKernelArg(kernel, 0, sizeof(cl_mem), &input);
189 err = clSetKernelArg(kernel, 1, sizeof(cl_mem), &output);
190 err = clSetKernelArg(kernel, 2, sizeof(unsigned int), &count);
191 */
192
193 //use pointer instead of malloc + memcpy for global variables
194 //((args*)kernel.arguments)->input = (float*)malloc(sizeof(float) * count);
195 //memcpy(((args *)kernel.arguments)->input, input, sizeof(float) * count);
196 ((args*)kernel.arguments)->input = input;
197
198 //((args*)kernel.arguments)->output = (float*)malloc(sizeof(float) * count);
199 //memcpy(((args*)kernel.arguments)->output, output, sizeof(float));
200 ((args*)kernel.arguments)->output = output;
201
202 ((args*)kernel.arguments)->count = count;
203 //no malloc needed for non pointers
204
205 //clGetKernelWorkGroupInfo would get a local size optimal for a device, but is not needed here
206 local = LOCAL;
207
208 global = count;
209 /*
210 commands holds the "order" of devices
211 kernel holds program, which holds variables
212 offset not implemented
213 */
214 err = clEnqueueNDRangeKernel(kernel, global, local);
215
216 //Replaces clEnqueueReadBuffer, which takes one of the saved variables and puts it out to another one
217 memcpy(results, output, sizeof(float) * count);
218
219 //verifies that all values in results are actually squared
220 correct = 0;
221 for(int i = 0; i < count; i++)
222 {
223 if(results[i] == data[i] * data[i])
224 {
225 correct++;
226 }
227 }
228 printf("Computed '%d/%d' correct values!\n", correct, count);
229
230 //TODO: Think of using void * array instead of regular arguments to make freeing easier
231
232 free(((args*)kernel.arguments)->input);
233 free(((args*)kernel.arguments)->output);
234 /*
235 free(input);
236 free(output);
237 */
238 free(arguments);
239
240 return 0;
241}
242 Completed ABC example. Worked on
243
244 Think of ways to implement multiple kernel methods using square.cvl without breaking it.
245
246
247 Exact implementations for multiple kernel methods not clear yet. Next example with multiple methods uses files with the same method
248
249
Note: See TracBrowser for help on using the repository browser.