platform_ptr platform::create(cl_platform_id platform_id, unsigned start_id) { vector<unsigned> device_types = {CL_DEVICE_TYPE_GPU, CL_DEVICE_TYPE_ACCELERATOR, CL_DEVICE_TYPE_CPU}; vector<cl_device_id> ids; for (cl_device_type device_type : device_types) { auto known = ids.size(); cl_uint discoverd; auto err = clGetDeviceIDs(platform_id, device_type, 0, nullptr, &discoverd); if (err == CL_DEVICE_NOT_FOUND) { continue; // no devices of the type found } else if (err != CL_SUCCESS) { throwcl("clGetDeviceIDs", err); } ids.resize(known + discoverd); v2callcl(CAF_CLF(clGetDeviceIDs), platform_id, device_type, discoverd, (ids.data() + known)); } vector<detail::raw_device_ptr> devices; devices.resize(ids.size()); auto lift = [](cl_device_id ptr) { return detail::raw_device_ptr{ptr, false}; }; transform(ids.begin(), ids.end(), devices.begin(), lift); detail::raw_context_ptr context; context.reset(v2get(CAF_CLF(clCreateContext), nullptr, static_cast<unsigned>(ids.size()), ids.data(), pfn_notify, nullptr), false); vector<device_ptr> device_information; for (auto& device_id : devices) { device_information.push_back(device::create(context, device_id, start_id++)); } if (device_information.empty()) CAF_RAISE_ERROR("no devices for the platform found"); auto name = platform_info(platform_id, CL_PLATFORM_NAME); auto vendor = platform_info(platform_id, CL_PLATFORM_VENDOR); auto version = platform_info(platform_id, CL_PLATFORM_VERSION); return make_counted<platform>(platform_id, move(context), move(name), move(vendor), move(version), move(device_information)); }
void opencl_metainfo::initialize() { // get number of available platforms auto num_platforms = v1get<cl_uint>(CAF_CLF(clGetPlatformIDs)); // get platform ids std::vector<cl_platform_id> platforms(num_platforms); v2callcl(CAF_CLF(clGetPlatformIDs), num_platforms, platforms.data()); if (platforms.empty()) { throw std::runtime_error("no OpenCL platform found"); } // support multiple platforms -> "for (auto platform : platforms)"? auto platform = platforms.front(); // detect how many devices we got cl_uint num_devs = 0; cl_device_type dev_type = CL_DEVICE_TYPE_GPU; // try get some GPU devices and try falling back to CPU devices on error try { num_devs = v1get<cl_uint>(CAF_CLF(clGetDeviceIDs), platform, dev_type); } catch (std::runtime_error&) { dev_type = CL_DEVICE_TYPE_CPU; num_devs = v1get<cl_uint>(CAF_CLF(clGetDeviceIDs), platform, dev_type); } // get available devices std::vector<cl_device_id> ds(num_devs); v2callcl(CAF_CLF(clGetDeviceIDs), platform, dev_type, num_devs, ds.data()); std::vector<device_ptr> devices(num_devs); // lift raw pointer as returned by OpenCL to C++ smart pointers auto lift = [](cl_device_id ptr) { return device_ptr{ptr, false}; }; std::transform(ds.begin(), ds.end(), devices.begin(), lift); // create a context context_.reset(v2get(CAF_CLF(clCreateContext), nullptr, num_devs, ds.data(), pfn_notify, nullptr), false); for (auto& device : devices) { CAF_LOG_DEBUG("creating command queue for device(s)"); command_queue_ptr cmd_queue; try { cmd_queue.reset(v2get(CAF_CLF(clCreateCommandQueue), context_.get(), device.get(), unsigned{CL_QUEUE_PROFILING_ENABLE}), false); } catch (std::runtime_error&) { CAF_LOG_DEBUG("unable to create command queue for device"); } if (cmd_queue) { auto max_wgs = v3get<size_t>(CAF_CLF(clGetDeviceInfo), device.get(), unsigned{CL_DEVICE_MAX_WORK_GROUP_SIZE}); auto max_wid = v3get<cl_uint>(CAF_CLF(clGetDeviceInfo), device.get(), unsigned{CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS}); dim_vec max_wi_per_dim(max_wid); v2callcl(CAF_CLF(clGetDeviceInfo), device.get(), unsigned{CL_DEVICE_MAX_WORK_ITEM_SIZES}, sizeof(size_t) * max_wid, max_wi_per_dim.data()); devices_.push_back(device_info{std::move(device), std::move(cmd_queue), max_wgs, max_wid, max_wi_per_dim}); } } if (devices_.empty()) { std::string errstr = "could not create a command queue for any device"; CAF_LOG_ERROR(errstr); throw std::runtime_error(std::move(errstr)); } }