platform_manager::platform_manager() { cl_uint n = 0; cl_int err = ::clGetPlatformIDs(0, NULL, &n); OCLM_THROW_IF_EXCEPTION(err, "clGetPlatformIDs"); std::vector<cl_platform_id> platform_ids(n); err = ::clGetPlatformIDs(n, &platform_ids[0], NULL); OCLM_THROW_IF_EXCEPTION(err, "clGetPlatformIDs"); platforms.resize(n); std::copy(platform_ids.begin(), platform_ids.end(), platforms.begin()); default_platform = platforms[0]; default_device = default_platform.devices[0]; }
int main() { cl_int error_code = CL_SUCCESS; try { // find Intel platform cl_uint num_platforms = 0; error_code = clGetPlatformIDs(0, nullptr, &num_platforms); HANDLE_CL_ERROR(clGetPlatformIDs) std::unique_ptr<cl_platform_id[]> platform_ids( new cl_platform_id[static_cast<const std::size_t>(num_platforms)]); error_code = clGetPlatformIDs(num_platforms, platform_ids.get(), nullptr); HANDLE_CL_ERROR(clGetPlatformIDs) cl_platform_id platform = nullptr; for (std::size_t i = 0; i != static_cast<const std::size_t>(num_platforms); ++i) { std::size_t platform_name_size = 0; error_code = clGetPlatformInfo(platform_ids[i], CL_PLATFORM_NAME, 0, nullptr, &platform_name_size); HANDLE_CL_ERROR(clGetPlatformInfo) std::unique_ptr<char[]> platform_name(new char[platform_name_size]); error_code = clGetPlatformInfo(platform_ids[i], CL_PLATFORM_NAME, platform_name_size, platform_name.get(), nullptr); HANDLE_CL_ERROR(clGetPlatformInfo) if (std::strcmp(beignet_platform_name, platform_name.get()) == 0) { platform = platform_ids[i]; std::cout << "Platform: " << platform_name.get() << std::endl; break; } } if (platform == nullptr) { throw std::runtime_error(std::string("Couldn't find platform with name: ") + beignet_platform_name); } // find Intel GPU cl_device_id device = nullptr; error_code = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, nullptr); HANDLE_CL_ERROR(clGetDeviceIDs) std::size_t device_name_size = 0; error_code = clGetDeviceInfo(device, CL_DEVICE_NAME, 0, nullptr, &device_name_size); HANDLE_CL_ERROR(clGetDeviceInfo) std::unique_ptr<char[]> device_name(new char[device_name_size]); error_code = clGetDeviceInfo(device, CL_DEVICE_NAME, device_name_size, device_name.get(), nullptr); HANDLE_CL_ERROR(clGetDeviceInfo) std::cout << "Device: " << device_name.get() << std::endl; // create OpenCL context, command queue, program and kernel const auto context = clCreateContext(nullptr, 1, &device, nullptr, nullptr, &error_code); HANDLE_CL_ERROR(clCreateContext) const auto command_queue = clCreateCommandQueue(context, device, 0, &error_code); HANDLE_CL_ERROR(clCreateCommandQueue) const char *source_strings[1]; source_strings[0] = kernel_source; const std::size_t source_size = std::strlen(kernel_source); const auto program = clCreateProgramWithSource(context, 1, source_strings, &source_size, &error_code); HANDLE_CL_ERROR(clCreateProgramWithSource) error_code = clBuildProgram(program, 1, &device, "", nullptr, nullptr); HANDLE_CL_ERROR(clBuildProgram) const auto kernel = clCreateKernel(program, "print_hello", &error_code); HANDLE_CL_ERROR(clCreateKernel) // enqueue kernel and set event completion handler cl_event event; std::size_t global_work_size = 1; error_code = clEnqueueNDRangeKernel(command_queue, kernel, 1, nullptr, &global_work_size, nullptr, 0, nullptr, &event); HANDLE_CL_ERROR(clEnqueueNDRangeKernel) error_code = clSetEventCallback(event, CL_COMPLETE, [](cl_event, cl_int, void *) { std::cout << "OpenCL callback" << std::endl; // Notify the waiting thread that the kernel is completed { std::lock_guard<std::mutex> cond_lock(cond_mutex); kernel_complete = true; } cond_var.notify_one(); }, nullptr); HANDLE_CL_ERROR(clSetEventCallback) error_code = clFlush(command_queue); HANDLE_CL_ERROR(clFlush) // simulate work std::this_thread::sleep_for(std::chrono::seconds(1)); // do work, dependent on kernel completion { std::unique_lock<std::mutex> cond_lock(cond_mutex); while (!kernel_complete) { if (cond_var.wait_for(cond_lock, std::chrono::seconds(5)) == std::cv_status::timeout) { std::cout << "WARNING: A 5 second timeout has been reached on the condition variable.\n" " This may be a deadlock." << std::endl; } } } // When using Beignet, this will never be called as a deadlock will occur. std::cout << "Doing work, dependent on the kernel's completion" << std::endl; } catch (const std::exception &e) { std::cout << "Error: " << e.what() << std::endl; } catch (...) { std::cout << "Unknown error" << std::endl; } }