hello-opencl.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. * Copyright 2018 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. // This is a simple OpenCL Hello World that tests you have a functioning OpenCL setup.
  8. #include "cl.hpp"
  9. #include <initializer_list>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string>
  13. #include <vector>
  14. static inline void assert_cl(cl_int rc, const char* file, int line) {
  15. if (rc != CL_SUCCESS) {
  16. fprintf(stderr, "%s:%d, got OpenCL error code %d\n", file,line,rc);
  17. exit(1);
  18. }
  19. }
  20. #define cl_ok(err) assert_cl(err, __FILE__, __LINE__)
  21. int main(int, char**) {
  22. std::vector<cl::Platform> platforms;
  23. cl_ok(cl::Platform::get(&platforms));
  24. std::vector<cl::Device> devices;
  25. for (cl::Platform platform : platforms) {
  26. std::vector<cl::Device> platform_devices;
  27. cl_ok(platform.getDevices(CL_DEVICE_TYPE_ALL, &platform_devices));
  28. devices.insert(devices.end(), platform_devices.begin(), platform_devices.end());
  29. }
  30. if (devices.empty()) {
  31. fprintf(stderr, "No OpenCL devices available. :(\n");
  32. return 1;
  33. }
  34. // To keep things simple we'll only create single-device cl::Contexts.
  35. for (cl::Device device : devices) {
  36. std::string name,
  37. version,
  38. driver,
  39. vendor,
  40. extensions;
  41. cl_ok(device.getInfo(CL_DEVICE_NAME, &name));
  42. cl_ok(device.getInfo(CL_DEVICE_VERSION, &version));
  43. cl_ok(device.getInfo(CL_DEVICE_VENDOR, &vendor));
  44. cl_ok(device.getInfo(CL_DEVICE_EXTENSIONS, &extensions));
  45. cl_ok(device.getInfo(CL_DRIVER_VERSION, &driver));
  46. fprintf(stdout, "Using %s%s, vendor %s, version %s, extensions:\n%s\n",
  47. version.c_str(), name.c_str(), vendor.c_str(), driver.c_str(), extensions.c_str());
  48. std::vector<cl::Device> devices = { device };
  49. // Some APIs can't return their cl_int error but might still fail,
  50. // so they take a pointer. cl_ok() is really handy here too.
  51. cl_int ok;
  52. cl::Context ctx(devices,
  53. nullptr/*optional cl_context_properties*/,
  54. nullptr/*optional error reporting callback*/,
  55. nullptr/*context argument for error reporting callback*/,
  56. &ok);
  57. cl_ok(ok);
  58. cl::Program program(ctx,
  59. "__kernel void mul(__global const float* a, "
  60. " __global const float* b, "
  61. " __global float* dst) {"
  62. " int i = get_global_id(0); "
  63. " dst[i] = a[i] * b[i]; "
  64. "} ",
  65. /*and build now*/true,
  66. &ok);
  67. cl_ok(ok);
  68. std::vector<float> a,b,p;
  69. for (int i = 0; i < 1000; i++) {
  70. a.push_back(+i);
  71. b.push_back(-i);
  72. p.push_back( 0);
  73. }
  74. cl::Buffer
  75. A(ctx, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR , sizeof(float)*a.size(), a.data()),
  76. B(ctx, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR , sizeof(float)*b.size(), b.data()),
  77. P(ctx, CL_MEM_WRITE_ONLY| CL_MEM_HOST_READ_ONLY, sizeof(float)*p.size());
  78. cl::Kernel mul(program, "mul", &ok);
  79. cl_ok(ok);
  80. cl_ok(mul.setArg(0, A));
  81. cl_ok(mul.setArg(1, B));
  82. cl_ok(mul.setArg(2, P));
  83. cl::CommandQueue queue(ctx, device);
  84. cl_ok(queue.enqueueNDRangeKernel(mul, cl::NDRange(0) /*offset*/
  85. , cl::NDRange(1000) /*size*/));
  86. cl_ok(queue.enqueueReadBuffer(P, true/*block until read is done*/
  87. , 0 /*offset in bytes*/
  88. , sizeof(float)*p.size() /*size in bytes*/
  89. , p.data()));
  90. fprintf(stdout, "OpenCL sez: %g x %g = %g\n", a[42], b[42], p[42]);
  91. for (int i = 0; i < 1000; i++) {
  92. if (p[i] != a[i]*b[i]) {
  93. return 1;
  94. }
  95. }
  96. }
  97. return 0;
  98. }