ViennaCL - The Vienna Computing Library: examples/tutorial/custom-context.cpp Source File

ViennaCL - The Vienna Computing Library 1.7.1 Free open-source GPU-accelerated linear algebra and solver library. |

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
custom-context.cpp
Go to the documentation of this file.
1 /* =========================================================================
2 Copyright (c) 2010-2016, Institute for Microelectronics,
3 Institute for Analysis and Scientific Computing,
4 TU Wien.
5 Portions of this software are copyright by UChicago Argonne, LLC.
6
7 -----------------
8 ViennaCL - The Vienna Computing Library
9 -----------------
10
11 Project Head: Karl Rupp rupp@iue.tuwien.ac.at
12
13 (A list of authors and contributors can be found in the PDF manual)
14
15 License: MIT (X11), see file LICENSE in the base directory
16 ============================================================================= */
17
25 // System headers
26 #include <iostream>
27 #include <string>
28
29 #ifndef VIENNACL_WITH_OPENCL
30 #define VIENNACL_WITH_OPENCL
31 #endif
32
33
34 // ViennaCL headers
35 #include "viennacl/ocl/backend.hpp"
36 #include "viennacl/vector.hpp"
37 #include "viennacl/matrix.hpp"
38 #include "viennacl/linalg/matrix_operations.hpp"
39 #include "viennacl/linalg/norm_2.hpp"
40 #include "viennacl/linalg/prod.hpp"
41
42
43
55 static const char * my_compute_program =
56 "__kernel void elementwise_prod(\n"
57 " __global const float * vec1,\n"
58 " __global const float * vec2, \n"
59 " __global float * result,\n"
60 " unsigned int size) \n"
61 "{ \n"
62 " for (unsigned int i = get_global_id(0); i < size; i += get_global_size(0))\n"
63 " result[i] = vec1[i] * vec2[i];\n"
64 "};\n";
65
69 int main()
70 {
71 typedef float ScalarType;
72
73
82 //manually set up a custom OpenCL context:
83 std::vector<cl_device_id> device_id_array;
84
85 //get all available devices
86 viennacl::ocl::platform pf;
87 std::cout << "Platform info: " << pf.info() << std::endl;
88 std::vector<viennacl::ocl::device> devices = pf.devices(CL_DEVICE_TYPE_DEFAULT);
89 std::cout << devices[0].name() << std::endl;
90 std::cout << "Number of devices for custom context: " << devices.size() << std::endl;
91
92 //set up context using all found devices:
93 for (std::size_t i=0; i<devices.size(); ++i)
94 {
95 device_id_array.push_back(devices[i].id());
96 }
97
98 std::cout << "Creating context..." << std::endl;
99 cl_int err;
100 cl_context my_context = clCreateContext(0, cl_uint(device_id_array.size()), &(device_id_array[0]), NULL, NULL, &err);
101 VIENNACL_ERR_CHECK(err);
102
103
104 //create two Vectors:
105 unsigned int vector_size = 10;
106 std::vector<ScalarType> vec1(vector_size);
107 std::vector<ScalarType> vec2(vector_size);
108 std::vector<ScalarType> result(vector_size);
109
110 //
111 // fill the operands vec1 and vec2:
112 //
113 for (unsigned int i=0; i<vector_size; ++i)
114 {
115 vec1[i] = static_cast<ScalarType>(i);
116 vec2[i] = static_cast<ScalarType>(vector_size-i);
117 }
118
119 //
120 // create memory in OpenCL context:
121 //
122 cl_mem mem_vec1 = clCreateBuffer(my_context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, vector_size * sizeof(ScalarType), &(vec1[0]), &err);
123 VIENNACL_ERR_CHECK(err);
124 cl_mem mem_vec2 = clCreateBuffer(my_context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, vector_size * sizeof(ScalarType), &(vec2[0]), &err);
125 VIENNACL_ERR_CHECK(err);
126 cl_mem mem_result = clCreateBuffer(my_context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, vector_size * sizeof(ScalarType), &(result[0]), &err);
127 VIENNACL_ERR_CHECK(err);
128
129 //
130 // create a command queue for each device:
131 //
132
133 std::vector<cl_command_queue> queues(devices.size());
134 for (std::size_t i=0; i<devices.size(); ++i)
135 {
136 queues[i] = clCreateCommandQueue(my_context, devices[i].id(), 0, &err);
137 VIENNACL_ERR_CHECK(err);
138 }
139
140 //
141 // create and build a program in the context:
142 //
143 std::size_t source_len = std::string(my_compute_program).length();
144 cl_program my_prog = clCreateProgramWithSource(my_context, 1, &my_compute_program, &source_len, &err);
145 err = clBuildProgram(my_prog, 0, NULL, NULL, NULL, NULL);
146
147 /* char buffer[1024];
148 cl_build_status status;
149 clGetProgramBuildInfo(my_prog, devices[1].id(), CL_PROGRAM_BUILD_STATUS, sizeof(cl_build_status), &status, NULL);
150 clGetProgramBuildInfo(my_prog, devices[1].id(), CL_PROGRAM_BUILD_LOG, sizeof(char)*1024, &buffer, NULL);
151 std::cout << "Build Scalar: Err = " << err << " Status = " << status << std::endl;
152 std::cout << "Log: " << buffer << std::endl;*/
153
154 VIENNACL_ERR_CHECK(err);
155
156 //
157 // create a kernel from the program:
158 //
159 const char * kernel_name = "elementwise_prod";
160 cl_kernel my_kernel = clCreateKernel(my_prog, kernel_name, &err);
161 VIENNACL_ERR_CHECK(err);
162
163
164 //
165 // Execute elementwise_prod kernel on first queue: result = vec1 .* vec2;
166 //
167 err = clSetKernelArg(my_kernel, 0, sizeof(cl_mem), (void*)&mem_vec1);
168 VIENNACL_ERR_CHECK(err);
169 err = clSetKernelArg(my_kernel, 1, sizeof(cl_mem), (void*)&mem_vec2);
170 VIENNACL_ERR_CHECK(err);
171 err = clSetKernelArg(my_kernel, 2, sizeof(cl_mem), (void*)&mem_result);
172 VIENNACL_ERR_CHECK(err);
173 err = clSetKernelArg(my_kernel, 3, sizeof(unsigned int), (void*)&vector_size);
174 VIENNACL_ERR_CHECK(err);
175 std::size_t global_size = vector_size;
176 std::size_t local_size = vector_size;
177 err = clEnqueueNDRangeKernel(queues[0], my_kernel, 1, NULL, &global_size, &local_size, 0, NULL, NULL);
178 VIENNACL_ERR_CHECK(err);
179
180
181 //
182 // Read and output result:
183 //
184 err = clEnqueueReadBuffer(queues[0], mem_vec1, CL_TRUE, 0, sizeof(ScalarType)*vector_size, &(vec1[0]), 0, NULL, NULL);
185 VIENNACL_ERR_CHECK(err);
186 err = clEnqueueReadBuffer(queues[0], mem_result, CL_TRUE, 0, sizeof(ScalarType)*vector_size, &(result[0]), 0, NULL, NULL);
187 VIENNACL_ERR_CHECK(err);
188
189 std::cout << "vec1 : ";
190 for (std::size_t i=0; i<vec1.size(); ++i)
191 std::cout << vec1[i] << " ";
192 std::cout << std::endl;
193
194 std::cout << "vec2 : ";
195 for (std::size_t i=0; i<vec2.size(); ++i)
196 std::cout << vec2[i] << " ";
197 std::cout << std::endl;
198
199 std::cout << "result: ";
200 for (std::size_t i=0; i<result.size(); ++i)
201 std::cout << result[i] << " ";
202 std::cout << std::endl;
203
210 viennacl::ocl::setup_context(0, my_context, device_id_array, queues);
211 viennacl::ocl::switch_context(0); //activate the new context (only mandatory with context-id not equal to zero)
212
216 std::cout << "Existing context: " << my_context << std::endl;
217 std::cout << "ViennaCL uses context: " << viennacl::ocl::current_context().handle().get() << std::endl;
218
222 viennacl::vector<ScalarType> vcl_vec1(mem_vec1, vector_size);
223 viennacl::vector<ScalarType> vcl_vec2(mem_vec2, vector_size);
224 viennacl::vector<ScalarType> vcl_result(mem_result, vector_size);
225 viennacl::scalar<ScalarType> vcl_s = 2.0;
226
227 std::cout << "Standard vector operations within ViennaCL:" << std::endl;
228 vcl_result = vcl_s * vcl_vec1 + vcl_vec2;
229
230 std::cout << "vec1 : ";
231 std::cout << vcl_vec1 << std::endl;
232
233 std::cout << "vec2 : ";
234 std::cout << vcl_vec2 << std::endl;
235
236 std::cout << "result: ";
237 std::cout << vcl_result << std::endl;
238
244 std::cout << "Using existing kernel within the OpenCL backend of ViennaCL:" << std::endl;
245 viennacl::ocl::program & my_vcl_prog = viennacl::ocl::current_context().add_program(my_prog, "my_compute_program");
246 viennacl::ocl::kernel & my_vcl_kernel = my_vcl_prog.add_kernel(my_kernel, "elementwise_prod");
247 viennacl::ocl::enqueue(my_vcl_kernel(vcl_vec1, vcl_vec2, vcl_result, static_cast<cl_uint>(vcl_vec1.size()))); //Note that std::size_t might differ between host and device. Thus, a cast to cl_uint is necessary here.
248
249 std::cout << "vec1 : ";
250 std::cout << vcl_vec1 << std::endl;
251
252 std::cout << "vec2 : ";
253 std::cout << vcl_vec2 << std::endl;
254
255 std::cout << "result: ";
256 std::cout << vcl_result << std::endl;
257
258
264 viennacl::matrix<ScalarType> vcl_matrix(mem_vec1, 3, 3);
265
266 vcl_vec2.resize(3); //note that the resize operation leads to new memory, thus vcl_vec2 is now at a different memory location (values are copied)
267 vcl_result.resize(3); //note that the resize operation leads to new memory, thus vcl_vec2 is now at a different memory location (values are copied)
268 vcl_result = viennacl::linalg::prod(vcl_matrix, vcl_vec2);
269
270 std::cout << "result of matrix-vector product: ";
271 std::cout << vcl_result << std::endl;
272
277 std::cout << "!!!! TUTORIAL COMPLETED SUCCESSFULLY !!!!" << std::endl;
278
279 return EXIT_SUCCESS;
280 }
281
viennacl::ocl::program::add_kernel
viennacl::ocl::kernel & add_kernel(cl_kernel kernel_handle, std::string const &kernel_name)
Adds a kernel to the program.
Definition: context.hpp:765
viennacl::scalar
This class represents a single scalar value on the GPU and behaves mostly like a built-in scalar type...
Definition: forwards.h:227
norm_2.hpp
Generic interface for the l^2-norm. See viennacl/linalg/vector_operations.hpp for implementations...
matrix_operations.hpp
Implementations of dense matrix related operations including matrix-vector products.
viennacl::ocl::platform
Wrapper class for an OpenCL platform.
Definition: platform.hpp:45
prod.hpp
Generic interface for matrix-vector and matrix-matrix products. See viennacl/linalg/vector_operations...
viennacl::ocl::kernel
Represents an OpenCL kernel within ViennaCL.
Definition: kernel.hpp:58
matrix.hpp
Implementation of the dense matrix class.
main
int main()
Definition: bisect.cpp:91
viennacl::ocl::platform::devices
std::vector< device > devices(cl_device_type dtype=CL_DEVICE_TYPE_DEFAULT)
Returns the available devices of the supplied device type.
Definition: platform.hpp:91
viennacl::ocl::current_context
viennacl::ocl::context & current_context()
Convenience function for returning the current context.
Definition: backend.hpp:213
viennacl::matrix
A dense matrix class.
Definition: forwards.h:375
viennacl::ocl::context::handle
const viennacl::ocl::handle< cl_context > & handle() const
Returns the context handle.
Definition: context.hpp:611
VIENNACL_ERR_CHECK
#define VIENNACL_ERR_CHECK(err)
Definition: error.hpp:681
viennacl::linalg::prod
VectorT prod(std::vector< std::vector< T, A1 >, A2 > const &matrix, VectorT const &vector)
Definition: prod.hpp:102
viennacl::ocl::context::add_program
viennacl::ocl::program & add_program(cl_program p, std::string const &prog_name)
Adds a program to the context.
Definition: context.hpp:368
viennacl::ocl::handle::get
const OCL_TYPE & get() const
Definition: handle.hpp:191
viennacl::vector< ScalarType >
viennacl::ocl::program
Wrapper class for an OpenCL program.
Definition: program.hpp:42
backend.hpp
Implementations of the OpenCL backend, where all contexts are stored in.
viennacl::ocl::switch_context
void switch_context(long i)
Convenience function for switching the current context.
Definition: backend.hpp:219
viennacl::ocl::enqueue
void enqueue(KernelType &k, viennacl::ocl::command_queue const &queue)
Enqueues a kernel in the provided queue.
Definition: enqueue.hpp:50
vector.hpp
The vector type with operator-overloads and proxy classes is defined here. Linear algebra operations ...
ScalarType
float ScalarType
Definition: fft_1d.cpp:42
viennacl::ocl::platform::info
std::string info() const
Returns an information string.
Definition: platform.hpp:71
viennacl::ocl::setup_context
void setup_context(long i, std::vector< cl_device_id > const &devices)
Convenience function for setting devices for a context.
Definition: backend.hpp:231