3.7 OpenCL C++ Wapper向量加法

Khronos组织也在后续的OpenCL标准中定义了一套C++ Wapper API。C++ API与C API是对应的(比如,cl::Memory对应cl_mem),不过C++需要对异常和类进行处理。下面的代码对应的与代码清单3.4中的C代码相对应。

  1. #define __CL_ENABLE_EXCEPTIONS
  2. #include <CL/cl.hpp>
  3. #include <iostream>
  4. #include <fstream>
  5. #include <string>
  6. #include <vector>
  7. int main(){
  8. const int elements = 2048;
  9. size_t datasize = sizeof(int) * elements;
  10. int *A = new int[elements];
  11. int *B = new int[elements];
  12. int *C = new int[elements];
  13. for (int i = 0; i < elements; i++){
  14. A[i] = i;
  15. B[i] = i;
  16. }
  17. try{
  18. // Query for platforms
  19. std::vector<cl::Platform> platforms;
  20. cl::Platform::get(&platforms);
  21. // Get a list of devices on this platform
  22. std::vector<cl::Device> devices;
  23. platforms[0].getDevices(CL_DEVICE_TYPE_ALL, &devices);
  24. // Create a context for the devices
  25. cl::Context context(devices);
  26. // Create a command-queue for the first device
  27. cl::CommandQueue queue = cl::CommandQueue(context, devices[0]);
  28. // Create the memory buffers
  29. cl::Buffer bufferA = cl::Buffer(context, CL_MEM_READ_ONLY, datasize);
  30. cl::Buffer bufferB = cl::Buffer(context, CL_MEM_READ_ONLY, datasize);
  31. cl::Buffer bufferC = cl::Buffer(context, CL_MEM_WRITE_ONLY, datasize);
  32. // Copy the input data to the input buffers using the
  33. // command-queue for the first device
  34. queue.enqueueWriteBuffer(bufferA, CL_TRUE, 0, datasize, A);
  35. queue.enqueueWriteBuffer(bufferB, CL_TRUE, 0, datasize, B);
  36. // Read the program source
  37. std::ifstream sourceFile("vector_add_kernel.cl");
  38. std::string sourceCode(std::istreambuf_iterator<char>(sourceFile), (std::istreambuf_iterator<char>()));
  39. cl::Program::Source source(1, std::make_pair(sourceCode.c_str(), sourceCode.length() + 1);
  40. // Create the program from the source code
  41. cl::Program program = cl::Program(context, source);
  42. // Build the program for the devices
  43. program.build(devices);
  44. // Create the kernel
  45. cl::Kernel vecadd_kernel(program, "vecadd");
  46. // Set the kernel arguments
  47. vecadd_kernel.setArg(0, bufferA);
  48. vecadd_kernel.setArg(1, bufferB);
  49. vecadd_kernel.setArg(2, bufferC);
  50. // Execute the kernel
  51. cl::NDRange gloabl(elements);
  52. cl::NDRange local(256);
  53. queue.enqueueNDRangeKernel(vecadd_kernel, cl::NullRange, gloabl, local);
  54. // Copy the output data back to the host
  55. queue.enqueueReadBuffer(bufferC, CL_TRUE, 0, datasize, C);
  56. } catch(cl::Error error){
  57. std::cout << error.what() << "(" << error.err() << ")" << std::endl;
  58. }
  59. }

代码清单3.5 使用C++ Wapper实现的OpenCL向量相加