source: CIVL/examples/opencl/2.15/multiple.cvl@ 41340c1

1.23 2.0 main test-branch
Last change on this file since 41340c1 was 6317abc, checked in by Ziqing Luo <ziqing@…>, 11 years ago

renaming opencl version files
move div0 to arithmetic

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

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