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

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

square.cvl type cast from void pointer to int in progress

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

  • Property mode set to 100644
File size: 8.3 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 int count;
28 */
29 void * input;
30 void * output;
31 void * count;
32
33}args;
34
35/*
36 args * argument - Takes in the struct, which is changed for every program using a different kernel
37*/
38cl_kernel clCreateKernel(args * argument, char * function)
39{
40 cl_kernel kernel;
41 kernel.arguments = argument;
42 kernel.method = function;
43
44 return kernel;
45}
46
47/*
48 This is the kernel that processes compute with
49 int workgroup - Gives the workgroup that a particular process came from, made by clEnqueueNDRangeKernel
50 int global_id - Gives the global_id that a particular process has, given by workfunc
51 int local_id - Gives the local_id that a particular process has, given by workfunc
52 float* input - Kernel argument
53 float* output - Kernel argument
54 int count - Kernel argument
55*/
56void square(int workgroup, int global_id, int local_id, float* input, float* output, int count)
57{
58 //int i = get_global_id(0);
59 int i = global_id;
60 if (i < count)
61 {
62 output[i] = input[i] * input[i];
63 //printf("output[%d] is %d\n", i, output[i]);
64 }
65}
66/*
67 workfunc assigns local and global ids, before calling the kernel.
68 Note: The function should be identical in all transformations except the calling of the kernel, which means that it cannot be in openCLshared.cvl
69 size_t local - The size of the workgroups, used to calculate blocks
70 size_t global - The total amount of work to be done
71 cl_kernel param - Holds the data for local_id, global_id, and the workgroup
72 Use the print statement to get a better idea of what it means to split workgroups, local_ids, and global_ids
73*/
74void empty()
75{
76}
77
78void workfunc(size_t local, size_t global, cl_kernel param)
79{
80 $proc procs[local];
81 for(int i = local * param.workgroup; i < local * param.workgroup + local; i++)
82 {
83 param.local_id = i % local;
84 param.global_id = i;
85 printf("My workgroup id is %d, my global id is %d, my local id is %d, and my method is %s\n", param.workgroup, param.global_id, param.local_id, param.method);
86
87 procs[param.local_id] = $spawn square(param.workgroup, param.global_id, param.local_id, ((args*)param.arguments)->input, ((args*)param.arguments)->output, (int*)(((args*)param.arguments)->count));
88
89 }
90 for(int j = 0; j < local; j++)
91 {
92 $wait(procs[j]);
93 }
94}
95
96/*
97 Splits up and spawns processes based on global and local, using block
98 TODO: remove cl_command_queue completely and put into a "just in case" file, currently not needed
99 cl_command_queue commands - Holds a queue of the order that devices are to be executed
100 cl_kernel kernel - Holds all the arguments for the kernel, as well as local_id, global_id, and the workgroup
101 size_t global - The total amount of work to be done
102 size_t local - Number to split into workgroups by
103*/
104int clEnqueueNDRangeKernel(cl_kernel kernel, size_t global, size_t local)
105{
106
107 $assert(global % local == 0);
108 int numworkgroups = global/local;
109 cl_kernel param[numworkgroups];
110 $proc procs[numworkgroups];
111 //consider $parfor
112
113 /*
114 $domain(1) dom = {0 .. numworkgroups - 1};
115
116 $for(int i: dom)
117 {
118 param[i] = kernel;
119 param[i].workgroup = i;
120 }
121 $parfor(int i: dom)
122 {
123 workfunc(local, global, param[i]);
124 }
125 */
126
127 for(int i = 0; i < global/local; i++)
128 {
129 param[i] = kernel;
130 param[i].workgroup = i;
131 procs[i] = $spawn workfunc(local, global, param[i]);
132 }
133
134 //this part here is the new clFinish(commands);
135 for(int i = 0; i < global/local; i++)
136 {
137 $wait(procs[i]);
138 }
139
140 return CL_SUCCESS;
141
142}
143
144
145int main(int argc, char** argv)
146{
147 //Make function pointers for every method
148 void (*squarePtr) (int, int, int, float *, float *, int);
149 squarePtr = &square;
150
151 args * arguments;
152 arguments = (args*)malloc(sizeof(args));
153
154 float data[DATA_SIZE]; // original data set given to device
155 float results[DATA_SIZE]; // results returned from device
156 unsigned int correct; // number of correct results returned
157
158 size_t global; // global domain size for our calculation
159 size_t local; // local domain size for our calculation
160
161 cl_device_id device_id; // compute device id
162 cl_context context; // compute context
163 cl_command_queue commands; // compute command queue
164 //cl_program program; // compute program
165 cl_kernel kernel; // compute kernel
166 int err;
167
168 float * input; // device memory used for the input array
169 float * output; // device memory used for the output array
170
171 //Puts in data for input
172 unsigned int count = DATA_SIZE;
173 for(int i = 0; i < count; i++)
174 {
175 data[i] = i;
176 }
177
178
179 //clCreateProgram is far different from the real version, this just stores parameters for the kernel
180 //In order to make this clear, it is clCreateProgram and not something like clCreateProgramFromSource, which actually exists in openCL code
181 //program = clCreateProgram(arguments);
182
183 kernel = clCreateKernel(arguments, "square");
184
185 //replaces clCreateBuffer
186 input = (float *) malloc(sizeof(float) * count);
187 output = (float *) malloc(sizeof(float) * count);
188
189
190 //replaces clEnqueueWriteBuffer, puts data into the input to be put into the kernel arguments
191 memcpy(input, data, sizeof(float) * count);
192
193 /*
194 err = 0;
195 err = clSetKernelArg(kernel, 0, sizeof(cl_mem), &input);
196 err = clSetKernelArg(kernel, 1, sizeof(cl_mem), &output);
197 err = clSetKernelArg(kernel, 2, sizeof(unsigned int), &count);
198 */
199
200 //use pointer instead of malloc + memcpy for global variables
201 //((args*)kernel.arguments)->input = (float*)malloc(sizeof(float) * count);
202 //memcpy(((args *)kernel.arguments)->input, input, sizeof(float) * count);
203 ((args*)kernel.arguments)->input = input;
204
205 //((args*)kernel.arguments)->output = (float*)malloc(sizeof(float) * count);
206 //memcpy(((args*)kernel.arguments)->output, output, sizeof(float));
207 ((args*)kernel.arguments)->output = output;
208
209 ((args*)kernel.arguments)->count = (int *)malloc(sizeof(int));
210 memcpy(((args*)kernel.arguments)->count, &count, sizeof(int));
211 //no malloc needed for non pointers
212
213 //clGetKernelWorkGroupInfo would get a local size optimal for a device, but is not needed here
214 local = LOCAL;
215
216 global = count;
217 /*
218 commands holds the "order" of devices
219 kernel holds program, which holds variables
220 offset not implemented
221 */
222 err = clEnqueueNDRangeKernel(kernel, global, local);
223
224 //Replaces clEnqueueReadBuffer, which takes one of the saved variables and puts it out to another one
225 memcpy(results, output, sizeof(float) * count);
226
227 //verifies that all values in results are actually squared
228 correct = 0;
229 for(int i = 0; i < count; i++)
230 {
231 if(results[i] == data[i] * data[i])
232 {
233 correct++;
234 }
235 }
236 printf("Computed '%d/%d' correct values!\n", correct, count);
237
238 //TODO: Think of using void * array instead of regular arguments to make freeing easier
239
240 free(((args*)kernel.arguments)->input);
241 free(((args*)kernel.arguments)->output);
242 /*
243 free(input);
244 free(output);
245 */
246 free(arguments);
247
248 return 0;
249}
250/*Note, pointers to global memory cannot be stored in local memory
251support for global, local, constant and group, local being the default
252private (local) - variable assignment, or malloc + memcpy
253
254global - pointer with memory location. For regular non pointer variables, make a pointer and assign it to it, then use the pointer
255Global variables can be declared in program source but they must use the "constant" address space qualifier and need to be initialized.
256You cannot have global variables that can be modified by kernels and where the modified values are persistent across work-groups and kernel executions.
257For this, you should use memory objects instead.
258
259Constant is just like global, but read only
260
261group - ???
262*/
263
264
Note: See TracBrowser for help on using the repository browser.