#ifndef GPU_GPU_PRIMITIVE_HPP
#define GPU_GPU_PRIMITIVE_HPP
#include "common/cache_blob.hpp"
#include "common/primitive.hpp"
#include "common/primitive_exec_types.hpp"
#include "gpu/gpu_resource.hpp"
namespace dnnl {
namespace impl {
namespace gpu {
struct primitive_t : public impl::primitive_t {
using impl::primitive_t::primitive_t;
struct compute_block_t {
compute_block_t(impl::primitive_t *primitive) : primitive_(primitive) {}
virtual ~compute_block_t() = default;
status_t get_cache_blob_size(
impl::engine_t *engine, size_t *size) const {
if (primitive_)
return primitive_->get_cache_blob_size(engine, size);
return get_cache_blob_size_impl(engine, size);
}
status_t get_cache_blob(
impl::engine_t *engine, cache_blob_t &blob) const {
if (primitive_) return primitive_->get_cache_blob(engine, blob);
return get_cache_blob_impl(engine, blob);
}
bool empty() const { return empty_impl(); }
const impl::primitive_t *primitive() const { return primitive_; }
private:
virtual bool empty_impl() const { return !bool(primitive_); }
virtual status_t get_cache_blob_size_impl(
impl::engine_t *engine, size_t *size) const {
assert(!"unexpected");
return status::runtime_error;
}
virtual status_t get_cache_blob_impl(
impl::engine_t *engine, cache_blob_t &blob) const {
assert(!"unexpected");
return status::runtime_error;
}
impl::primitive_t *primitive_;
};
status_t create_nested_primitive(
std::shared_ptr<impl::primitive_t> &primitive,
const std::shared_ptr<primitive_desc_t> &pd,
impl::engine_t *engine) {
if (!pd) return status::invalid_arguments;
std::pair<std::shared_ptr<impl::primitive_t>, cache_state_t> p;
CHECK(pd->create_primitive_nested(p, engine, cache_blob()));
if (p.second == cache_state_t::kernel_hit) {
creation_cached_state_ = cache_state_t::nested_primitive_hit;
}
primitive = p.first;
register_compute_block(new compute_block_t(primitive.get()));
return status::success;
}
status_t get_cache_blob_size(
impl::engine_t *engine, size_t *size) const override {
if (!size) return status::invalid_arguments;
for (const auto &cb : compute_blocks()) {
if (cb->empty()) continue;
CHECK(cb->get_cache_blob_size(engine, size));
}
return status::success;
}
status_t get_cache_blob(
impl::engine_t *engine, cache_blob_t &blob) const override {
for (const auto &cb : compute_blocks()) {
if (cb->empty()) continue;
CHECK(cb->get_cache_blob(engine, blob));
}
return status::success;
}
status_t create_resource(
impl::engine_t *engine, resource_mapper_t &mapper) const override {
if (mapper.has_resource(this)) return status::success;
auto r = utils::make_unique<gpu_resource_t>();
if (!r) return status::out_of_memory;
CHECK(init_res_storage(engine, r.get()));
mapper.add(this, std::move(r));
for (const auto &cb : compute_blocks()) {
if (cb->empty()) continue;
if (cb->primitive())
CHECK(cb->primitive()->create_resource(engine, mapper));
}
return status::success;
}
protected:
virtual status_t init_res_storage(
impl::engine_t *engine, gpu_resource_t *r) const {
return status::success;
}
void register_compute_block(compute_block_t *cb) {
compute_blocks_.emplace_back(cb);
}
const std::vector<std::unique_ptr<compute_block_t>> &
compute_blocks() const {
return compute_blocks_;
}
private:
void register_primitive(impl::primitive_t *primitive) {
compute_blocks_.emplace_back(new compute_block_t(primitive));
}
std::vector<std::unique_ptr<compute_block_t>> compute_blocks_;
};
} } }
#endif