integration 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ class Integration
2
+ VERSION = '0.1.2'
3
+ end
@@ -0,0 +1,29 @@
1
+ all: cl.so
2
+
3
+ CC=gcc
4
+ CL_HEADERS_PATH=
5
+ LIBOPENCL_PATH=
6
+
7
+
8
+ UNAME := $(shell uname)
9
+ ifeq ($(UNAME), Linux)
10
+ # do something Linux-y
11
+ OPENCL_LIBRARY_CALL=-lOpenCL
12
+ endif
13
+ ifeq ($(UNAME), Solaris)
14
+ # do something Solaris-y
15
+ OPENCL_LIBRARY_CALL=-framework OpenCL
16
+ endif
17
+
18
+
19
+
20
+ cl.so: integration_host.o
21
+ $(CC) -shared -o cl.so integration_host.o -I $(CL_HEADERS_PATH) -L $(LIBOPENCL_PATH) $(OPENCL_LIBRARY_CALL)
22
+
23
+
24
+ integration_host.o: integration_host.c
25
+ $(CC) -fpic -c integration_host.c
26
+
27
+ clean:
28
+ rm cl.so integration_host.o
29
+
@@ -0,0 +1,151 @@
1
+ // This file contains the host code of the openCL supported integration
2
+ #include <stdio.h>
3
+ #include <stdio.h>
4
+ #include <stdlib.h>
5
+ #include <stdlib.h>
6
+ #include <limits.h> //For PATH_MAX
7
+
8
+ // import OpenCL headers assuming OS is a linux version or MAC
9
+ #ifdef __APPLE__
10
+ #include<OpenCL/opencl.h>
11
+ #else
12
+ #include<CL/cl.h>
13
+ #endif
14
+
15
+ #define MAX_SOURCE_SIZE (0x100000) // maximum size allowed for the kernel text
16
+
17
+ // these are the available integration methods
18
+ enum methods{
19
+ rectangle,
20
+ trapezoid,
21
+ simpson,
22
+ adaptive_quadrature,
23
+ gauss,
24
+ romberg,
25
+ monte_carlo
26
+ };
27
+
28
+ double opencl_integration(double lower, double upper, int n, char* f,
29
+ enum methods method, char* path_to_kerne) {
30
+
31
+ char* source_str;
32
+ size_t source_size;
33
+ int i = 0;
34
+ double dx = (upper - lower) / n;
35
+ double *results = (double*) malloc(n * sizeof(double));
36
+
37
+ // read the corresponding kernel
38
+ FILE* fp;
39
+ sprintf(path_to_kerne, "%s%s", path_to_kerne, "/unidimensional_kernel.cl");
40
+ fp = fopen(path_to_kerne, "r");
41
+
42
+ // if the kernel file doesn't exist, stop the execution
43
+ if(fp == 0) {
44
+ printf("kernel file not found\n");
45
+ exit(0);
46
+ }
47
+
48
+ char *temp_source;
49
+ // allocate memory for kenel code
50
+ temp_source = (char*) malloc(sizeof(char) * MAX_SOURCE_SIZE);
51
+ source_str = (char*) malloc(sizeof(char) * MAX_SOURCE_SIZE);
52
+
53
+ temp_source[0] = '\0'; // make temp_source a null string
54
+ char line[100];
55
+ // read the text of the kernel into temp_source
56
+ while(!feof(fp)) {
57
+ if (fgets(line, 100, fp)) {
58
+ sprintf(temp_source, "%s%s",temp_source, line);
59
+ }
60
+ }
61
+
62
+ // create the complete kernel code appending,
63
+ // f() - integrating function
64
+ sprintf(source_str, "double f(double x){return (%s);}\n%s", f, temp_source);
65
+
66
+ // printf("\nfunction----------------------------\n%s\n--------------------------\n", source_str);
67
+ source_size = strlen(source_str);
68
+ fclose(fp);
69
+ free(temp_source);
70
+
71
+ cl_platform_id platform_id = NULL;
72
+ cl_device_id device_id = NULL;
73
+ cl_uint ret_num_devices;
74
+ cl_uint ret_num_platforms;
75
+ cl_int ret;
76
+ ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);
77
+ // CL_DEVICE_TYPE_CPU is being used currently as the testing value
78
+ ret = clGetDeviceIDs( platform_id, CL_DEVICE_TYPE_CPU, 1, &device_id, &ret_num_devices);
79
+
80
+ // create kernel
81
+ cl_context context = clCreateContext( NULL, 1, &device_id, NULL, NULL, &ret);
82
+ // create command queue
83
+ cl_command_queue command_queue = clCreateCommandQueue(context, device_id, 0, &ret);
84
+
85
+ // create memory buffers to share memory with kernel program
86
+ cl_mem lower_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(double) , NULL, &ret);
87
+ cl_mem dx_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(double) , NULL, &ret);
88
+ cl_mem n_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(int) , NULL, &ret);
89
+ cl_mem method_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(int) , NULL, &ret);
90
+ cl_mem result_obj = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(double) * n , NULL, &ret);
91
+ //cl_mem epsilon_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(double) , NULL, &ret);
92
+ //cl_mem golden_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(double) , NULL, &ret);
93
+
94
+ // writes the input values into the allocated memory buffers
95
+ ret = clEnqueueWriteBuffer(command_queue, lower_obj, CL_TRUE, 0, sizeof(double) , &lower , 0, NULL, NULL);
96
+ ret = clEnqueueWriteBuffer(command_queue, dx_obj , CL_TRUE, 0, sizeof(double) , &dx , 0, NULL, NULL);
97
+ ret = clEnqueueWriteBuffer(command_queue, n_obj , CL_TRUE, 0, sizeof(int) , &n , 0, NULL, NULL);
98
+ ret = clEnqueueWriteBuffer(command_queue, method_obj, CL_TRUE, 0, sizeof(int) , &method, 0, NULL, NULL);
99
+ //ret = clEnqueueWriteBuffer(command_queue, epsilon_obj , CL_TRUE, 0, sizeof(double) , &epsilon , 0, NULL, NULL);
100
+ //ret = clEnqueueWriteBuffer(command_queue, golden_obj , CL_TRUE, 0, sizeof(double) , &golden , 0, NULL, NULL);
101
+
102
+ // create kernel program
103
+ cl_program program = clCreateProgramWithSource(context, 1, (const char **)&source_str, (const size_t *)&source_size, &ret);
104
+ // build the kernel program. Still the code isn't being executed
105
+ // memory buffers haven't involved. Any error at this stage MAY be a syntax error of kernel code
106
+ ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);
107
+ // this gives error message only if the kernel code includes any syntax error
108
+ if(ret == CL_BUILD_PROGRAM_FAILURE) printf("\nerror while building kernel: %d\n", ret);
109
+ // create the kernel calling the kernel function 'minimize'
110
+ cl_kernel kernel = clCreateKernel(program, "integrate", &ret);
111
+
112
+ // set arguments of kernel function
113
+ ret = clSetKernelArg(kernel, 0 , sizeof(cl_mem) , (void *)&lower_obj);
114
+ ret = clSetKernelArg(kernel, 1 , sizeof(cl_mem) , (void *)&dx_obj);
115
+ ret = clSetKernelArg(kernel, 2 , sizeof(cl_mem) , (void *)&n_obj);
116
+ ret = clSetKernelArg(kernel, 3 , sizeof(cl_mem) , (void *)&method_obj);
117
+ ret = clSetKernelArg(kernel, 4 , sizeof(cl_mem) * n, (void *)&result_obj);
118
+ //ret = clSetKernelArg(kernel, 9 , sizeof(cl_mem) , (void *)&epsilon_obj);
119
+ //ret = clSetKernelArg(kernel, 10, sizeof(cl_mem) , (void *)&golden_obj);
120
+
121
+ size_t global_item_size = n;
122
+ // enqueue the jobs and let them to be solved by kernel program
123
+ ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, NULL, 0, NULL, NULL);
124
+
125
+ // retrieve results from the shared memory buffers
126
+ ret = clEnqueueReadBuffer(command_queue, result_obj, CL_TRUE, 0, sizeof(double) * n, results, 0, NULL, NULL);
127
+
128
+ // clear the allocated memory
129
+ ret = clFlush(command_queue);
130
+ ret = clFinish(command_queue);
131
+ ret = clReleaseKernel(kernel);
132
+ ret = clReleaseProgram(program);
133
+
134
+ ret = clReleaseMemObject(lower_obj);
135
+ ret = clReleaseMemObject(dx_obj);
136
+ ret = clReleaseMemObject(n_obj);
137
+ ret = clReleaseMemObject(method_obj);
138
+ //ret = clReleaseMemObject(epsilon_obj);
139
+ //ret = clReleaseMemObject(golden_obj);
140
+
141
+ ret = clReleaseCommandQueue(command_queue);
142
+ ret = clReleaseContext(context);
143
+ free(source_str);
144
+
145
+ double final_result = 0;
146
+ for(i = 0; i < n; ++i) {
147
+ final_result += results[i];
148
+ }
149
+
150
+ return final_result;
151
+ }
@@ -0,0 +1,251 @@
1
+ require 'ffi'
2
+
3
+ module OpenCLMinimization extend FFI::Library
4
+
5
+ MAX_ITERATIONS_DEFAULT = 100000
6
+ EPSILON_DEFAULT = 0.00001
7
+ GOLDEN_DEFAULT = 0.3819660
8
+ SQRT_EPSILON_DEFAULT = 0.00001
9
+ PATH_TO_KERNEL = File.expand_path(File.dirname(__FILE__))
10
+
11
+ ffi_lib "#{File.expand_path(File.dirname(__FILE__))}/cl.so"
12
+
13
+ # attack with the opencl_minimize of min_host.c
14
+ attach_function 'opencl_minimize', [:int, :pointer, :pointer, :pointer, :int, :string, :string,
15
+ :string, :pointer, :pointer, :int, :int, :float, :float, :float, :string], :void
16
+
17
+ # Classic GodlSectionMinimizer minimization method.
18
+ # Basic minimization algorithm. Slow, but robust.
19
+ # See Unidimensional for methods.
20
+ # == Usage
21
+ # n = 3
22
+ # start_point = [1, 3, 5]
23
+ # expected_point = [1.5, 3.5, 5.5]
24
+ # end_point = [3, 5, 7]
25
+ # f = "pow((x-2)*(x-4)*(x-6), 2)+1"
26
+ # min = OpenCLMinimization::GodlSectionMinimizer.new(n, start_point, expected_point, end_point, f)
27
+ # min.minimize
28
+ # min.x_minimum
29
+ # min.f_minimum
30
+ #
31
+ class GodlSectionMinimizer
32
+ attr_reader :x_minimum
33
+ attr_reader :f_minimum
34
+
35
+ attr_writer :max_iterations
36
+ attr_writer :epsilon
37
+ attr_writer :golden
38
+
39
+ # == Parameters:
40
+ # * <tt>n</tt>: Number of Jobs
41
+ # * <tt>start_point</tt>: Lower possible value
42
+ # * <tt>expected_point</tt>: Initial point
43
+ # * <tt>end_point</tt>: Higher possible value
44
+ # * <tt>f</tt>: Original function string
45
+ #
46
+ def initialize(n, start_point, expected_point, end_point, f)
47
+ @n = n
48
+ @start_point = start_point
49
+ @expected_point = expected_point
50
+ @end_point = end_point
51
+ @f = f
52
+ @max_iterations = MAX_ITERATIONS_DEFAULT
53
+ @epsilon = EPSILON_DEFAULT
54
+ @golden = GOLDEN_DEFAULT
55
+ @sqrt_epsilon = SQRT_EPSILON_DEFAULT
56
+ end
57
+
58
+ def minimize
59
+ # create Buffers for inputs and outputs
60
+ start_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
61
+ expected_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
62
+ end_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
63
+ x_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
64
+ f_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
65
+
66
+ # set inputs
67
+ start_buffer.write_array_of_float(@start_point)
68
+ expected_buffer.write_array_of_float(@expected_point)
69
+ end_buffer.write_array_of_float(@end_point)
70
+
71
+ # call minimizer
72
+ OpenCLMinimization::opencl_minimize(@n, start_buffer, expected_buffer, end_buffer, 0, @f, "", "", x_buffer,
73
+ f_buffer, 0, @max_iterations, @epsilon, @golden, @sqrt_epsilon, PATH_TO_KERNEL)
74
+
75
+ @x_minimum = Array.new(@n)
76
+ @f_minimum = Array.new(@n)
77
+ # read results
78
+ @x_minimum = x_buffer.read_array_of_float(@n)
79
+ @f_minimum = f_buffer.read_array_of_float(@n)
80
+ end
81
+ end
82
+
83
+ # Classic Newton-Raphson minimization method.
84
+ # Requires first and second derivative
85
+ # == Usage
86
+ # n = 3
87
+ # expected_point = [1, 100, 1000]
88
+ # f = "(x-3)*(x-3)+5"
89
+ # fd = "2*(x-3)"
90
+ # fdd = "2"
91
+ # min = OpenCLMinimization::NewtonRampsonMinimizer.new(n, expected_point, f, fd, fdd)
92
+ # min.minimize
93
+ # min.x_minimum
94
+ # min.f_minimum
95
+ #
96
+ class NewtonRampsonMinimizer
97
+ attr_reader :x_minimum
98
+ attr_reader :f_minimum
99
+
100
+ attr_writer :max_iterations
101
+ attr_writer :epsilon
102
+ attr_writer :golden
103
+
104
+ # == Parameters:
105
+ # * <tt>n</tt>: Number of Jobs
106
+ # * <tt>expected_point</tt>: Initial point
107
+ # * <tt>f</tt>: Original function
108
+ # * <tt>fd</tt>: First derivative function string
109
+ # * <tt>fdd</tt>: Second derivative function string
110
+ #
111
+ def initialize(n, expected_point, f, fd, fdd)
112
+ @n = n
113
+ @expected_point = expected_point
114
+ @f = f
115
+ @fd = fd
116
+ @fdd = fdd
117
+ @max_iterations = MAX_ITERATIONS_DEFAULT
118
+ @epsilon = EPSILON_DEFAULT
119
+ @golden = GOLDEN_DEFAULT
120
+ @sqrt_epsilon = SQRT_EPSILON_DEFAULT
121
+ end
122
+
123
+ def minimize
124
+ # create Buffers for inputs and outputs
125
+ expected_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
126
+ x_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
127
+ f_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
128
+
129
+ # set inputs
130
+ expected_buffer.write_array_of_float(@expected_point)
131
+
132
+ # call minimizer
133
+ OpenCLMinimization::opencl_minimize(@n, nil, expected_buffer, nil, 1, @f, @fd, @fdd, x_buffer, f_buffer, 0,
134
+ @max_iterations, @epsilon, @golden, @sqrt_epsilon, PATH_TO_KERNEL)
135
+
136
+ @x_minimum = Array.new(@n)
137
+ @f_minimum = Array.new(@n)
138
+ # read results
139
+ @x_minimum = x_buffer.read_array_of_float(@n)
140
+ @f_minimum = f_buffer.read_array_of_float(@n)
141
+ end
142
+ end
143
+
144
+ # = Bisection Minimizer.
145
+ # Basic minimization algorithm. Slow, but robust.
146
+ # See Unidimensional for methods.
147
+ # == Usage.
148
+ # n = 3
149
+ # start_point = [1, 3, 5]
150
+ # expected_point = [1.5, 3.5, 5.5]
151
+ # end_point = [3, 5, 7]
152
+ # f = "pow((x-2)*(x-4)*(x-6), 2)+1"
153
+ # min = OpenCLMinimization::BisectionMinimizer.new(n, start_point, expected_point, end_point, f)
154
+ # min.minimize
155
+ # min.x_minimum
156
+ # min.f_minimum
157
+ #
158
+ class BisectionMinimizer < GodlSectionMinimizer
159
+
160
+ def minimize
161
+ # create Buffers for inputs and outputs
162
+ start_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
163
+ expected_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
164
+ end_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
165
+ x_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
166
+ f_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
167
+
168
+ # set inputs
169
+ start_buffer.write_array_of_float(@start_point)
170
+ expected_buffer.write_array_of_float(@expected_point)
171
+ end_buffer.write_array_of_float(@end_point)
172
+
173
+ # call minimizer
174
+ OpenCLMinimization::opencl_minimize(@n, start_buffer, expected_buffer, end_buffer, 2, @f, "", "", x_buffer,
175
+ f_buffer, 0, @max_iterations, @epsilon, @golden, @sqrt_epsilon, PATH_TO_KERNEL)
176
+
177
+ @x_minimum = Array.new(@n)
178
+ @f_minimum = Array.new(@n)
179
+ # read results
180
+ @x_minimum = x_buffer.read_array_of_float(@n)
181
+ @f_minimum = f_buffer.read_array_of_float(@n)
182
+ end
183
+ end
184
+
185
+ # Direct port of Brent algorithm found on GSL.
186
+ # See Unidimensional for methods.
187
+ # == Usage
188
+ # n = 3
189
+ # start_point = [1, 3, 5]
190
+ # expected_point = [1.5, 3.5, 5.5]
191
+ # end_point = [3, 5, 7]
192
+ # f = "pow((x-2)*(x-4)*(x-6), 2)+1"
193
+ # min = OpenCLMinimization::BisectionMinimizer.new(n, start_point, expected_point, end_point, f)
194
+ # min.minimize
195
+ # min.x_minimum
196
+ # min.f_minimum
197
+ #
198
+ class BrentMinimizer
199
+ attr_reader :x_minimum
200
+ attr_reader :f_minimum
201
+
202
+ attr_writer :max_iterations
203
+ attr_writer :epsilon
204
+ attr_writer :golden
205
+ attr_writer :sqrt_epsilon
206
+
207
+ # == Parameters:
208
+ # * <tt>n</tt>: Number of Jobs
209
+ # * <tt>start_point</tt>: Lower possible value
210
+ # * <tt>expected_point</tt>: Initial point
211
+ # * <tt>end_point</tt>: Higher possible value
212
+ # * <tt>f</tt>: Original function string
213
+ #
214
+ def initialize(n, start_point, expected_point, end_point, f)
215
+ @n = n
216
+ @start_point = start_point
217
+ @expected_point = expected_point
218
+ @end_point = end_point
219
+ @f = f
220
+ @max_iterations = MAX_ITERATIONS_DEFAULT
221
+ @epsilon = EPSILON_DEFAULT
222
+ @golden = GOLDEN_DEFAULT
223
+ @sqrt_epsilon = SQRT_EPSILON_DEFAULT
224
+ end
225
+
226
+ def minimize
227
+ # create Buffers for inputs and outputs
228
+ start_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
229
+ expected_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
230
+ end_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
231
+ x_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
232
+ f_buffer = FFI::Buffer.alloc_inout(:pointer, @n)
233
+
234
+ # set inputs
235
+ start_buffer.write_array_of_float(@start_point)
236
+ expected_buffer.write_array_of_float(@expected_point)
237
+ end_buffer.write_array_of_float(@end_point)
238
+
239
+ # call minimizer
240
+ OpenCLMinimization::opencl_minimize(@n, start_buffer, expected_buffer, end_buffer, 3, @f, "", "", x_buffer,
241
+ f_buffer, 0, @max_iterations, @epsilon, @golden, @sqrt_epsilon, PATH_TO_KERNEL)
242
+
243
+ @x_minimum = Array.new(@n)
244
+ @f_minimum = Array.new(@n)
245
+ # read results
246
+ @x_minimum = x_buffer.read_array_of_float(@n)
247
+ @f_minimum = f_buffer.read_array_of_float(@n)
248
+ end
249
+ end
250
+
251
+ end
@@ -0,0 +1,47 @@
1
+ // This is the kenel code for unidimensional integration methods.
2
+ // This is loaded into memory at runtime and a functions will be appended at run time,
3
+ // double f(double x) - integrating function
4
+
5
+
6
+ double rectangle(int i, double a, double dx);
7
+ double trapezoid(int i, double a, double dx);
8
+ double simpson(int i, double a, double dx);
9
+ double romberg(int i, double a, double dx);
10
+
11
+ __kernel void integrate(__global const double *a, __global const double *dx, __global const double *n,
12
+ __global int *method, __global double *results) {
13
+
14
+ // Get the index of the current element to be processed
15
+ int i = get_global_id(0);
16
+
17
+ // Do the operation
18
+ if(i <= n) {
19
+ int m = *method;
20
+ switch(m) {
21
+ case 0: results[i] = rectangle(i, *a, *dx);
22
+ break;
23
+ case 1: results[i] = trapezoid(i, *a, *dx);
24
+ break;
25
+ case 2: results[i] = simpson(i, *a, *dx);
26
+ break;
27
+ case 3: results[i] = romberg(i, *a, *dx);
28
+ break;
29
+ }
30
+ }
31
+ }
32
+
33
+ double rectangle(int i, double a, double dx) {
34
+ double midpoint = a + (i + 0.5) * dx;
35
+ return dx * f(midpoint);
36
+ }
37
+
38
+ double trapezoid(int i, double a, double dx) {
39
+ double lower = a + i * dx;
40
+ return (0.5 * dx * (f(lower) + f(lower + dx)));
41
+ }
42
+
43
+ double simpson(int i, double a, double dx) {
44
+ double lower = a + i * dx;
45
+ return (dx / 6) * (f(lower) + 4 * f(lower + 0.5 * dx) + f(lower + dx));
46
+ }
47
+