source: CIVL/examples/opencl/2.15/multiple.cvl@ bb03188

main test-branch
Last change on this file since bb03188 was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

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

  • Property mode set to 100644
File size: 6.0 KB
Line 
1#include <civlc.cvh>
2
3//verify examples/translation/openclversion2.15/multiple.cvl
4
5#include "cl.cvl"
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <civlc.h>
10#include "multiplekernel.cvl"
11
12int numArgs = 2;
13int numKernels = 4;
14/*
15 args * argument - Takes in the struct, which is changed for every program using a different kernel
16 int mallocflag[numArgs] - A flag for each element in the param array. If the mallocflag is set to 1, it means that it will be freed by clReleaseKernel
17*/
18typedef struct
19{
20 void * param[numArgs];
21 int mallocflag[numArgs];
22}args;
23/*
24 clCreateKernel in this iteration turns each flag to 0 to start off with, otherwise it gets a symbolic expression
25*/
26cl_kernel clCreateKernel(args * argument, char * function)
27{
28 cl_kernel kernel;
29 kernel.arguments = argument;
30 kernel.method = function;
31
32 for(int j = 0; j < numArgs; j++)
33 {
34 ((args*)kernel.arguments)->mallocflag[j] = 0;
35 }
36
37 return kernel;
38}
39/*
40 Checks the flag to make sure that it was a local variable that must be freed every step of the way
41*/
42void clReleaseKernel(cl_kernel kernel)
43{
44 for (int i = 0; i < numArgs; i++)
45 {
46 //printf("I am argument %d with value %d\n", i, ((args*)kernel.arguments)->mallocflag[i]);
47 if (((args*)kernel.arguments)->mallocflag[i] == 1)
48 {
49 //printf("and I pass the flag check\n");
50 free(((args*)kernel.arguments)->param[i]);
51 }
52 }
53}
54/*
55 workfunc assigns local and global ids, before calling the kernel.
56 Note: The function should be identical in all transformations except the calling of the kernel, which means that it cannot be in openCLshared.cvl
57 size_t local - The size of the workgroups, used to calculate blocks
58 size_t global - The total amount of work to be done
59 cl_kernel param - Holds the data for local_id, global_id, and the workgroup
60 Use the print statement to get a better idea of what it means to split workgroups, local_ids, and global_ids
61*/
62void workfunc(size_t local, size_t global, cl_kernel param)
63{
64 $proc procs[local];
65 char * reduceChar = "add";
66 char * reduceCharTwo = "sub";
67 for(int i = local * param.workgroup; i < local * param.workgroup + local; i++)
68 {
69 int n = *(int*)(((args*)param.arguments)->param[0]);
70 param.local_id = i % local;
71 param.global_id = i;
72 //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);
73 //printf("workfunc var is %s,\n", reduceChar);
74 //printf(" kernel method name is %s\n", param.method);
75 if(strcmp(param.method, reduceChar) == 0)
76 {
77 procs[param.local_id] = $spawn add(param.workgroup, param.global_id, param.local_id, n, ((args*)param.arguments)->param[1]);
78 }
79
80 if(strcmp(param.method, reduceCharTwo) == 0)
81 {
82 procs[param.local_id] = $spawn sub(param.workgroup, param.global_id, param.local_id, n, ((args*)param.arguments)->param[1]);
83 }
84
85 }
86 for(int j = 0; j < local; j++)
87 {
88 $wait(procs[j]);
89 }
90}
91
92/*
93 Splits up and spawns processes based on global and local, using block
94 cl_kernel kernel - Holds all the arguments for the kernel, as well as local_id, global_id, and the workgroup
95 size_t global - The total amount of work to be done
96 size_t local - Number to split into workgroups by
97*/
98int clEnqueueNDRangeKernel(cl_kernel kernel, size_t global, size_t local)
99{
100
101 $assert((global % local == 0));
102 int numworkgroups = global/local;
103 cl_kernel param[numworkgroups];
104 $proc procs[numworkgroups];
105 //consider $parfor
106
107 /*
108 $domain(1) dom = {0 .. numworkgroups - 1};
109
110 $for(int i: dom)
111 {
112 param[i] = kernel;
113 param[i].workgroup = i;
114 }
115 $parfor(int i: dom)
116 {
117 workfunc(local, global, param[i]);
118 }
119 */
120
121 for(int i = 0; i < global/local; i++)
122 {
123 param[i] = kernel;
124 param[i].workgroup = i;
125 procs[i] = $spawn workfunc(local, global, param[i]);
126 }
127
128 //this part here is the new clFinish(commands);
129 for(int i = 0; i < global/local; i++)
130 {
131 $wait(procs[i]);
132 }
133
134 return CL_SUCCESS;
135
136}
137
138int main(int argc, char** argv)
139{
140 int global = 1;
141 int local = 1;
142
143 args arguments[numKernels];
144 //arguments = (args*)malloc(sizeof(args) * numKernels);
145 //Must have enough arguments for each kernel
146 //try not on the heap
147
148 int one = 1;
149 int counter = 0;
150 //don't need to put on the heap
151
152 //cl_kernel *kernels = (cl_kernel*)malloc(numKernels * sizeof(cl_kernel));
153 cl_kernel kernels[numKernels];
154
155 //printf("%d, %d\n", star, *one);
156
157 char * in = (char*)malloc(sizeof(char)*3);
158 strcpy(in, "add");
159
160 char * out = (char*)malloc(sizeof(char)*3);
161 strcpy(out, "sub");
162
163 //For loop to create multiple kernels, the programmer must put the loop himself
164 for (int i = 0; i < numKernels; i++)
165 {
166 if((i % 2) == 0)
167 {
168 kernels[i] = clCreateKernel(arguments+i, in);
169
170 }
171
172 else
173 {
174 kernels[i] = clCreateKernel(arguments+i, out);
175 }
176
177 }
178 //For each kernel, put in the variables
179 for (int j = 0; j < numKernels; j++)
180 {
181
182 ((args*)kernels[j].arguments)->param[0] = (int*)malloc(sizeof(int));
183 ((args*)kernels[j].arguments)->mallocflag[0] = 1;
184 memcpy(((args*)kernels[j].arguments)->param[0], &one, sizeof(int));
185
186 //param[0] is a __local variable, so it gets the flag put to 1
187
188 //printf("I am kernel of index %d, with a value of %d\n", j, ((args*)kernels[j].arguments)->param[0]);
189
190 ((args*)kernels[j].arguments)->param[1] = &counter;
191 //This is a __global variable, so it does not get the flag changed in this iteration.
192 //TODO: determine if global variables were freed by clReleaseKernel or the programmer.
193 }
194
195 //printf("assigned properly\n");
196
197 for (int i = 0; i < numKernels; i++)
198 {
199 clEnqueueNDRangeKernel(kernels[i], global, local);
200 }
201 int ans = *((int*)((args*)kernels[0].arguments)->param[1]);
202 //memcpy(ans, &((args*)kernels[0].arguments)->param[1], sizeof(int));
203 printf("There are %d kernels, and the final value is %d\n", numKernels, ans);
204
205 for (int k = 0; k < numKernels; k++)
206 {
207 clReleaseKernel(kernels[k]);
208 }
209
210 free(in);
211 free(out);
212
213 return 0;
214}
215
216
Note: See TracBrowser for help on using the repository browser.