#ifndef GPU_INTEL_ENGINE_HPP
#define GPU_INTEL_ENGINE_HPP
#include <cassert>
#include <memory>
#include <vector>
#include <initializer_list>
#include "common/c_types_map.hpp"
#include "common/engine_impl.hpp"
#include "common/primitive.hpp"
#include "common/primitive_desc_iterator.hpp"
#include "common/resource.hpp"
#include "common/verbose.hpp"
#include "xpu/utils.hpp"
#include "gpu/gpu_engine.hpp"
#include "gpu/intel/compute/device_info.hpp"
#include "gpu/intel/compute/dispatch.hpp"
#include "gpu/intel/compute/kernel.hpp"
#include "gpu/intel/compute/kernel_ctx.hpp"
namespace gemmstone {
namespace dsl {
struct kernel_t;
}
}
namespace dnnl {
namespace impl {
namespace gpu {
namespace intel {
namespace jit {
struct generator_base_t;
namespace dsl = gemmstone::dsl;
}
class engine_t : public gpu::engine_t {
public:
engine_t(impl::engine_impl_t *impl) : gpu::engine_t(impl) {}
virtual status_t init();
status_t init(const std::vector<uint8_t> &cache_blob);
const compute::device_info_t *device_info() const {
return device_info_.get();
}
virtual status_t create_kernel(
compute::kernel_t *kernel, jit::generator_base_t *jitter) const
= 0;
virtual status_t create_kernel(compute::kernel_t &kernel,
const jit::dsl::kernel_t &kernel_ir) const
= 0;
virtual status_t create_kernels(std::vector<compute::kernel_t> *kernels,
const std::vector<const char *> &kernel_names,
const compute::kernel_ctx_t &kernel_ctx) const
= 0;
status_t create_kernel_bundle(compute::kernel_bundle_t &bundle,
const std::vector<const char *> &kernel_names,
const compute::kernel_ctx_t &kernel_ctx) const {
std::vector<compute::kernel_t> kernels;
CHECK(create_kernels(&kernels, kernel_names, kernel_ctx));
bundle = compute::kernel_bundle_t(std::move(kernels), kernel_names);
return status::success;
}
virtual status_t create_kernel_from_binary(compute::kernel_t &kernel,
const xpu::binary_t &binary, const char *kernel_name,
const compute::program_src_t &src) const
= 0;
virtual status_t create_kernels_from_cache_blob(
const cache_blob_t &cache_blob,
std::vector<compute::kernel_t> &kernels,
const std::vector<const char *> &kernel_names) const
= 0;
status_t create_kernel_from_cache_blob(const cache_blob_t &cache_blob,
compute::kernel_t &kernel, const char *kernel_name) const {
std::vector<compute::kernel_t> kernels;
CHECK(create_kernels_from_cache_blob(
cache_blob, kernels, {kernel_name}));
if (kernels.size() != 1) return status::runtime_error;
kernel = std::move(kernels[0]);
return status::success;
}
status_t get_zero_pad_primitive(
impl::primitive_t *&result, const resource_mapper_t *&resources) {
std::call_once(zero_pad_init_, [&]() -> void {
zero_pad_desc_t desc;
desc.primitive_kind = primitive_kind::zero_pad;
primitive_desc_iterator_t it(
this, (op_desc_t *)&desc, nullptr, nullptr);
std::shared_ptr<primitive_desc_t> zero_pad_pd(*(++it));
if (zero_pad_pd == nullptr) return;
status_t status
= zero_pad_pd->create_primitive(zero_pad_primitive_, this);
if (status != status::success) { zero_pad_primitive_.reset(); }
});
result = zero_pad_primitive_.get();
resources = &zero_pad_resources_;
return result != nullptr ? status::success : status::unimplemented;
}
bool mayiuse_f16_accumulator_with_f16() const override {
switch (device_info_->gpu_arch()) {
case compute::gpu_arch_t::xe_lp:
case compute::gpu_arch_t::xe_hp:
case compute::gpu_arch_t::xe_hpg: return true;
default: return false;
}
}
bool mayiuse(compute::device_ext_t ext) const {
return device_info_->has(ext);
}
bool is_xe_lp() const {
return device_info_->gpu_arch() == compute::gpu_arch_t::xe_lp;
}
bool is_xe_hp() const {
return device_info_->gpu_arch() == compute::gpu_arch_t::xe_hp;
}
bool is_xe_hpg() const {
return device_info_->gpu_arch() == compute::gpu_arch_t::xe_hpg;
}
bool is_xe_hpc() const {
return device_info_->gpu_arch() == compute::gpu_arch_t::xe_hpc;
}
bool mayiuse_ngen_kernels() const {
return device_info_->mayiuse_ngen_kernels();
}
bool mayiuse_non_uniform_work_groups() const {
return device_info_->mayiuse_non_uniform_work_groups();
}
bool mayiuse_system_memory_allocators() const override {
return device_info_->mayiuse_system_memory_allocators();
}
bool mayiuse_sub_group(int size) const {
return device_info_->mayiuse_sub_group(size);
}
bool mayiuse_sub_group(std::initializer_list<int> sizes) const {
for (int size : sizes)
if (!mayiuse_sub_group(size)) return false;
return true;
}
bool mayiuse_block_reads_writes_with_sub_group(int size) const {
return size <= 16
? true
: device_info_->gpu_arch() >= compute::gpu_arch_t::xe_hpc;
}
bool mayiuse_large_grf_mode() const {
return device_info()->mayiuse_systolic();
}
compute::dispatch_t create_dispatch(
const memory_desc_t *md = nullptr) const {
return compute::dispatch_t(this, md);
}
virtual gpu_utils::device_id_t device_id() const = 0;
protected:
virtual status_t init_device_info() = 0;
virtual status_t init_device_info(const std::vector<uint8_t> &cache_blob) {
assert(!"unexpected");
return status::runtime_error;
}
~engine_t() override = default;
std::shared_ptr<compute::device_info_t> device_info_;
private:
std::shared_ptr<impl::primitive_t> zero_pad_primitive_;
resource_mapper_t zero_pad_resources_;
std::once_flag zero_pad_init_;
};
} } } }
extern "C" bool DNNL_API dnnl_impl_gpu_intel_mayiuse_ngen_kernels(
dnnl::impl::engine_t *engine);
extern "C" DNNL_API const char *dnnl_impl_gpu_intel_get_isa_name(
dnnl::impl::engine_t *engine);
#endif