integration 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+