#include "oneapi/dnnl/dnnl_config.h"
#if DNNL_GPU_RUNTIME == DNNL_RUNTIME_OCL
#include "graph/utils/ocl_usm_utils.hpp"
#include "common/cpp_compat.hpp"
namespace dnnl {
namespace impl {
namespace graph {
namespace utils {
namespace ocl {
namespace {
template <typename F>
struct ext_func_t {
ext_func_t(const char *name) {
for (size_t i = 0; i < intel_platforms().size(); ++i) {
auto p = intel_platforms()[i];
auto f = reinterpret_cast<F>(
xpu::ocl::clGetExtensionFunctionAddressForPlatform(
p, name));
auto it = ext_func_ptrs_.insert({p, f});
assert(it.second);
MAYBE_UNUSED(it);
}
}
template <typename... Args>
typename cpp_compat::invoke_result<F, Args...>::type operator()(
cl_platform_id platform, Args... args) const {
if (!ext_func_ptrs_.count(platform)) {
throw std::runtime_error("Don't support the platform");
}
auto f = ext_func_ptrs_.at(platform);
return f(args...);
}
private:
static const std::vector<cl_platform_id> &intel_platforms() {
static auto intel_platforms = get_intel_platforms();
return intel_platforms;
}
static std::vector<cl_platform_id> get_intel_platforms() {
cl_uint num_platforms = 0;
cl_int err = xpu::ocl::clGetPlatformIDs(0, nullptr, &num_platforms);
if (err != CL_SUCCESS) return {};
std::vector<cl_platform_id> platforms(num_platforms);
err = xpu::ocl::clGetPlatformIDs(
num_platforms, platforms.data(), nullptr);
if (err != CL_SUCCESS) return {};
std::vector<cl_platform_id> intel_platforms;
char vendor_name[128] = {};
for (cl_platform_id p : platforms) {
err = xpu::ocl::clGetPlatformInfo(p, CL_PLATFORM_VENDOR,
sizeof(vendor_name), vendor_name, nullptr);
if (err != CL_SUCCESS) continue;
if (std::string(vendor_name).find("Intel") != std::string::npos)
intel_platforms.push_back(p);
}
std::sort(intel_platforms.begin(), intel_platforms.end());
intel_platforms.erase(
std::unique(intel_platforms.begin(), intel_platforms.end()),
intel_platforms.end());
return intel_platforms;
}
std::unordered_map<cl_platform_id, F> ext_func_ptrs_;
};
}
void *malloc_shared(
cl_device_id dev, cl_context ctx, size_t size, size_t alignment) {
using clSharedMemAllocINTEL_func_t = void *(*)(cl_context, cl_device_id,
cl_ulong *, size_t, cl_uint, cl_int *);
if (size == 0) return nullptr;
static ext_func_t<clSharedMemAllocINTEL_func_t> ext_func(
"clSharedMemAllocINTEL");
cl_platform_id platform;
UNUSED_OCL_RESULT(xpu::ocl::clGetDeviceInfo(
dev, CL_DEVICE_PLATFORM, sizeof(platform), &platform, nullptr));
cl_int err;
void *p = ext_func(platform, ctx, dev, nullptr, size,
static_cast<cl_uint>(alignment), &err);
assert(dnnl::impl::utils::one_of(err, CL_SUCCESS, CL_OUT_OF_RESOURCES,
CL_OUT_OF_HOST_MEMORY, CL_INVALID_BUFFER_SIZE));
return p;
}
void *malloc_device(
cl_device_id dev, cl_context ctx, size_t size, size_t alignment) {
using clDeviceMemAllocINTEL_func_t = void *(*)(cl_context, cl_device_id,
cl_ulong *, size_t, cl_uint, cl_int *);
if (size == 0) return nullptr;
static ext_func_t<clDeviceMemAllocINTEL_func_t> ext_func(
"clDeviceMemAllocINTEL");
cl_platform_id platform;
UNUSED_OCL_RESULT(xpu::ocl::clGetDeviceInfo(
dev, CL_DEVICE_PLATFORM, sizeof(platform), &platform, nullptr));
cl_int err;
void *p = ext_func(platform, ctx, dev, nullptr, size,
static_cast<cl_uint>(alignment), &err);
assert(dnnl::impl::utils::one_of(err, CL_SUCCESS, CL_OUT_OF_RESOURCES,
CL_OUT_OF_HOST_MEMORY, CL_INVALID_BUFFER_SIZE));
return p;
}
void free(void *ptr, cl_device_id dev, cl_context ctx) {
if (nullptr == ptr) return;
using F = cl_int (*)(cl_context, void *);
static ext_func_t<F> ext_func("clMemBlockingFreeINTEL");
cl_platform_id platform;
UNUSED_OCL_RESULT(xpu::ocl::clGetDeviceInfo(
dev, CL_DEVICE_PLATFORM, sizeof(platform), &platform, nullptr));
cl_int err = ext_func(platform, ctx, ptr);
UNUSED_OCL_RESULT(err);
}
} } } } }
#endif