source: CIVL/examples/opencl/2.14/life.c

main
Last change on this file 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.3 KB
Line 
1/*
2 * Conway's Game of Life using OpenCL C. Originally from
3 * http://ptgmedia.pearsoncmg.com/images/art_chisnall_opencl/elementLinks/opencl.c.html
4 */
5
6#include <fcntl.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <math.h>
11#include <unistd.h>
12#include <limits.h>
13#include <sys/types.h>
14#include <sys/stat.h>
15#include <OpenCL/opencl.h>
16
17
18const char *kernel_source =
19"__kernel void life( \n"
20" constant bool*input, \n"
21" global bool* output, \n"
22" const unsigned int height, \n"
23" const unsigned int width) \n"
24"{ \n"
25" int i = get_global_id(0); \n"
26" int rowUp = i - width; \n"
27" int rowDown = i + width; \n"
28" bool outOfBounds = (i < width); \n"
29" outOfBounds |= (i > (width * (height-1))); \n"
30" outOfBounds |= (i % width == 0); \n"
31" outOfBounds |= (i % width == width-1); \n"
32" if (outOfBounds) { output[i] = false; return; } \n"
33" int neighbours = input[rowUp-1] + input[rowUp] + input[rowUp+1]; \n"
34" neighbours += input[i-1] + input[i+1]; \n"
35" neighbours += input[rowDown-1] + input[rowDown] + input[rowDown+1]; \n"
36" if (neighbours == 3 || (input[i] && neighbours == 2)) \n"
37" output[i] = true; \n"
38" else \n"
39" output[i] = false; \n"
40 "} \n";
41
42void fail(const char *message)
43{
44 fprintf(stderr, "%s\n", message);
45 exit(1);
46}
47
48cl_kernel createKernelFromSource(cl_device_id device_id, cl_context context,
49 const char *source, const char *name)
50{
51 int err;
52 // Load the source
53 cl_program program = clCreateProgramWithSource(context, 1, &source , NULL,
54 &err);
55 if (err != CL_SUCCESS) { fail("Unable to create program"); }
56
57 // Compile it.
58 err = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
59 if (err != CL_SUCCESS)
60 {
61 size_t len;
62 char buffer[2048];
63 clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG,
64 sizeof(buffer), buffer, &len);
65 fprintf(stderr, "%s\n", buffer);
66 fail("Unable to build program");
67 }
68 // Load it.
69 cl_kernel kernel = clCreateKernel(program, name, &err);
70 if (!kernel || err != CL_SUCCESS) { fail("Unable to create kernel"); }
71 clReleaseProgram(program);
72
73 return kernel;
74}
75
76// The board
77static const int width = 128;
78static const int height = 64;
79static const size_t board_size = width * height;
80static _Bool board[board_size];
81// Storage for the board.
82static cl_mem input;
83static cl_mem output;
84// OpenCL state
85static cl_command_queue queue;
86static cl_kernel kernel;
87static cl_device_id device_id;
88static cl_context context;
89
90void printBoard(void)
91{
92 unsigned i = 0;
93
94 for (unsigned y=0 ; y<height ; y++)
95 {
96 for (unsigned x=0 ; x<width ; x++)
97 {
98 putc(board[i++] ? '*' : ' ', stdout);
99 }
100 puts("");
101 }
102 puts("\n");
103}
104
105void createQueue(void)
106{
107 int err;
108 err = clGetDeviceIDs(NULL, CL_DEVICE_TYPE_ALL, 1, &device_id, NULL);
109 if (err != CL_SUCCESS) { fail("Unable to enumerate device IDs"); }
110
111 context = clCreateContext(0, 1, &device_id, NULL, NULL, &err);
112 if (!context) { fail("Unable to create context"); }
113
114 queue = clCreateCommandQueue(context, device_id, 0, &err);
115 if (!queue) { fail("Unable to create command queue"); }
116}
117
118void prepareKernel(void)
119{
120 input = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(board), NULL,
121 NULL);
122 output = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(board), NULL,
123 NULL);
124 if (!input || !output) { fail("Unable to create buffers"); }
125
126 int err = 0;
127 err = clSetKernelArg(kernel, 0, sizeof(cl_mem), &input);
128 err |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &output);
129 err |= clSetKernelArg(kernel, 2, sizeof(unsigned int), &height);
130 err |= clSetKernelArg(kernel, 3, sizeof(unsigned int), &width);
131 if (err != CL_SUCCESS) { fail("Unable to set arguments"); }
132}
133
134void runGame(int iterations)
135{
136 if (iterations == 0) { return; }
137 int err;
138 size_t workgroup_size;
139 err = clGetKernelWorkGroupInfo(kernel, device_id, CL_KERNEL_WORK_GROUP_SIZE,
140 sizeof(size_t), &workgroup_size, NULL);
141 if (err != CL_SUCCESS) { fail("Unable to get kernel work-group size"); }
142
143 // Send the board to the OpenCL stack
144 err = clEnqueueWriteBuffer(queue, input, CL_TRUE, 0,
145 sizeof(board), board, 0, NULL, NULL);
146 if (err != CL_SUCCESS) { fail("Unable to enqueue buffer"); }
147
148 for (unsigned int i=0 ; i<iterations ; i++)
149 {
150 // Run the kernel on every cell in the board
151 err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &board_size,
152 &workgroup_size, 0, NULL, NULL);
153 if (err) { fail("Unable to enqueue kernel"); }
154 if (i < iterations - 1)
155 {
156 // Copy the output to the input for the next iteration
157 err = clEnqueueCopyBuffer(queue, output, input, 0, 0,
158 sizeof(board), 0, NULL, NULL);
159 if (err) { fail("Unable to enqueue copy"); }
160 }
161 }
162
163 err = clEnqueueReadBuffer(queue, output, CL_TRUE, 0,
164 sizeof(board), board, 0, NULL, NULL );
165 if (err != CL_SUCCESS) { fail("Unable to read results"); }
166}
167
168int main(int argc, char** argv)
169{
170 srandomdev();
171 for(unsigned int i=0 ; i<board_size ; i++)
172 board[i] = random() > (INT_MAX / 2);
173
174 createQueue();
175
176 kernel = createKernelFromSource(device_id, context,
177 kernel_source, "life");
178
179 prepareKernel();
180
181 printBoard();
182 int iterations = 0;
183 do
184 {
185 printf("Run for how many iterations (0 to exit)? ");
186 scanf("%d", &iterations);
187 runGame(iterations);
188 printBoard();
189 } while(iterations > 0);
190
191 clReleaseMemObject(input);
192 clReleaseMemObject(output);
193 clReleaseKernel(kernel);
194 clReleaseCommandQueue(queue);
195 clReleaseContext(context);
196
197 return 0;
198}
Note: See TracBrowser for help on using the repository browser.