commit 07f78f6b3f9c4d2ab4254246deb26c2da4e3ec20 Author: Dakota St. Laurent Date: Thu Jun 4 13:48:36 2015 -0400 init commit; example 00 is working, example 01 is not diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d55fe9e --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# openCL C++ headers +CL/ + +# compiled files +*.out + +# THIS IS MY SWAP +# (vim swap files) +*.swp +*.swo diff --git a/README.md b/README.md new file mode 100644 index 0000000..2bef45a --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# OpenCL basic examples +here is my feeble attempt at learning OpenCL, please don't make fun of me too much :hamburger + +## example 00 +this example is based off of [this example](simpleopencl.blogspot.ca/2013/06/tutorial-simple-start-with-opencl-and-c.html) (example-ception), but it goes a bit further. In the blogspot example, two 10-element vectors are created and a thread is used for each pair of elements. In this example, 10 threads are spawned but two 100-element vectors are used, and it is shown how to split up a specific number of elements per thread. + +## example 01 +(**not complete yet**) timing results of large vectors added together on a CPU vs GPU. diff --git a/example00.cpp b/example00.cpp new file mode 100644 index 0000000..c41a496 --- /dev/null +++ b/example00.cpp @@ -0,0 +1,101 @@ +#include +#include "CL/cl.hpp" + +int main() { + // get all platforms (drivers), e.g. NVIDIA + std::vector all_platforms; + cl::Platform::get(&all_platforms); + + if (all_platforms.size()==0) { + std::cout<<" No platforms found. Check OpenCL installation!\n"; + exit(1); + } + cl::Platform default_platform=all_platforms[0]; + std::cout << "Using platform: "<()<<"\n"; + + // get default device (CPUs, GPUs) of the default platform + std::vector all_devices; + default_platform.getDevices(CL_DEVICE_TYPE_ALL, &all_devices); + if(all_devices.size()==0){ + std::cout<<" No devices found. Check OpenCL installation!\n"; + exit(1); + } + + // use device[1] because that's a GPU; device[0] is the CPU + cl::Device default_device=all_devices[1]; + std::cout<< "Using device: "<()<<"\n"; + + // a context is like a "runtime link" to the device and platform; + // i.e. communication is possible + cl::Context context({default_device}); + + // create the program that we want to execute on the device + cl::Program::Sources sources; + + // calculates for each element; C = A + B + std::string kernel_code= + " void kernel simple_add(global const int* A, global const int* B, global int* C, " + " global const int* N) {" + " int ID, Nthreads, n, ratio, start, stop;" + "" + " ID = get_global_id(0);" + " Nthreads = get_global_size(0);" + " n = N[0];" + "" + " ratio = (n / Nthreads);" // number of elements for each thread + " start = ratio * ID;" + " stop = ratio * (ID + 1);" + "" + " for (int i=start; i(default_device) << std::endl; + exit(1); + } + + // apparently OpenCL only likes arrays ... + // N holds the number of elements in the vectors we want to add + int N[1] = {100}; + int n = N[0]; + + // create buffers on device (allocate space on GPU) + cl::Buffer buffer_A(context, CL_MEM_READ_WRITE, sizeof(int) * n); + cl::Buffer buffer_B(context, CL_MEM_READ_WRITE, sizeof(int) * n); + cl::Buffer buffer_C(context, CL_MEM_READ_WRITE, sizeof(int) * n); + cl::Buffer buffer_N(context, CL_MEM_READ_ONLY, sizeof(int)); + + // create things on here (CPU) + int A[n], B[n]; + for (int i=0; i +#include "CL/cl.hpp" +#include + + +double time_add_vectors(int n, int k) { + // adds two vectors of size n, k times, returns total duration + std::clock_t start; + double duration; + + int A[n], B[n], C[n]; + for (int i=0; i all_platforms; + cl::Platform::get(&all_platforms); + + if (all_platforms.size()==0) { + std::cout<<" No platforms found. Check OpenCL installation!\n"; + exit(1); + } + cl::Platform default_platform=all_platforms[0]; + // std::cout << "Using platform: "<()<<"\n"; + + // get default device (CPUs, GPUs) of the default platform + std::vector all_devices; + default_platform.getDevices(CL_DEVICE_TYPE_ALL, &all_devices); + if(all_devices.size()==0){ + std::cout<<" No devices found. Check OpenCL installation!\n"; + exit(1); + } + + // use device[1] because that's a GPU; device[0] is the CPU + cl::Device default_device=all_devices[1]; + // std::cout<< "Using device: "<()<<"\n"; + + // a context is like a "runtime link" to the device and platform; + // i.e. communication is possible + cl::Context context({default_device}); + + // create the program that we want to execute on the device + cl::Program::Sources sources; + + /* + // calculates for each element; C = A + B + std::string kernel_code= + " void kernel simple_add(global const int* A, global const int* B, global int* C) {" + " C[get_global_id(0)] = A[get_global_id(0)] + B[get_global_id(0)];" + " }"; + sources.push_back({kernel_code.c_str(), kernel_code.length()}); + + cl::Program program(context, sources); + if (program.build({default_device}) != CL_SUCCESS) { + std::cout << "Error building: " << program.getBuildInfo(default_device) << std::endl; + exit(1); + } + + // create buffers on device (allocate space on GPU) + cl::Buffer buffer_A(context, CL_MEM_READ_WRITE, sizeof(int) * 10); + cl::Buffer buffer_B(context, CL_MEM_READ_WRITE, sizeof(int) * 10); + cl::Buffer buffer_C(context, CL_MEM_READ_WRITE, sizeof(int) * 10); + + // create things on here (CPU) + int A[] = {0,1,2,3,4,5,6,7,8,9}; + int B[] = {0,1,2,0,1,2,0,1,2,0}; + + // create a queue (a queue of commands that the GPU will execute) + cl::CommandQueue queue(context, default_device); + + // push write commands to queue + queue.enqueueWriteBuffer(buffer_A, CL_TRUE, 0, sizeof(int)*10, A); + queue.enqueueWriteBuffer(buffer_B, CL_TRUE, 0, sizeof(int)*10, B); + + // RUN ZE KERNEL + cl::KernelFunctor simple_add(cl::Kernel(program, "simple_add"), queue, cl::NullRange, cl::NDRange(10), cl::NullRange); + simple_add(buffer_A, buffer_B, buffer_C); + + int C[10]; + // read result from GPU to here + queue.enqueueReadBuffer(buffer_C, CL_TRUE, 0, sizeof(int)*10, C); + + std::cout << "result: {"; + for (int i=0; i<10; i++) { + std::cout << C[i] << " "; + } + std::cout << "}" << std::endl; + */ + return 0; +} +