#ifndef GPU_AMD_MIOPEN_LRN_HPP
#define GPU_AMD_MIOPEN_LRN_HPP
#include <miopen/miopen.h>
#include "common/c_types_map.hpp"
#include "common/lrn_pd.hpp"
#include "gpu/amd/engine.hpp"
#include "gpu/amd/miopen_lrn_impl.hpp"
#include "gpu/amd/sycl_hip_utils.hpp"
#include "gpu/gpu_primitive.hpp"
namespace dnnl {
namespace impl {
namespace gpu {
namespace amd {
struct miopen_lrn_fwd_t : public gpu::primitive_t {
using gpu::primitive_t::primitive_t;
struct pd_t : public lrn_fwd_pd_t {
using lrn_fwd_pd_t::lrn_fwd_pd_t;
DECLARE_COMMON_PD_T("hip:miopen:any", miopen_lrn_fwd_t);
status_t init(impl::engine_t *) {
using namespace data_type;
bool ok = is_fwd()
&& IMPLICATION(
desc()->alg_kind == alg_kind::lrn_within_channel,
ndims() == 4)
&& utils::one_of(src_md()->data_type, f32, f16)
&& src_md()->data_type == dst_md()->data_type
&& attr()->has_default_values() && desc_.local_size % 2
&& set_default_formats_common() && check_format()
&& memory_desc_wrapper(src_md())
== memory_desc_wrapper(dst_md());
if (!ok) return status::unimplemented;
if (has_zero_dim_memory()) return status::success;
lrn_impl_.reset(new miopen_lrn_fwd_impl_t());
CHECK(lrn_impl_->init(this));
return init_ws();
}
status_t init_ws() {
if (!is_training()) return status::success;
const size_t miopen_ws_size = lrn_impl_->get_workspace_size();
const size_t dst_size = memory_desc_wrapper(dst_md()).size();
const size_t ws_size = miopen_ws_size + dst_size;
dims_t dims = {(dim_t)ws_size};
return memory_desc_init_by_tag(ws_md_, ws_size ? 1 : 0, dims,
data_type::u8, format_tag::a);
}
bool check_format() const {
return (memory_desc_wrapper(src_md()).matches_one_of_tag(
format_tag::a, format_tag::ab, format_tag::abc,
format_tag::abcd)
&& memory_desc_wrapper(dst_md()).matches_one_of_tag(
format_tag::a, format_tag::ab, format_tag::abc,
format_tag::abcd));
}
bool is_training() const {
return desc_.prop_kind == prop_kind::forward_training;
}
std::shared_ptr<miopen_lrn_impl_base_t> lrn_impl_;
};
status_t execute(const exec_ctx_t &ctx) const override;
private:
const pd_t *pd() const { return (const pd_t *)primitive_t::pd().get(); }
};
struct miopen_lrn_bwd_t : public gpu::primitive_t {
using gpu::primitive_t::primitive_t;
struct pd_t : public lrn_bwd_pd_t {
using lrn_bwd_pd_t::lrn_bwd_pd_t;
DECLARE_COMMON_PD_T("hip:miopen:any", miopen_lrn_bwd_t);
status_t init(impl::engine_t *) {
using namespace data_type;
bool ok = !is_fwd()
&& IMPLICATION(
desc()->alg_kind == alg_kind::lrn_within_channel,
ndims() == 4)
&& utils::one_of(src_md()->data_type, f32, f16)
&& utils::everyone_is(src_md()->data_type,
diff_dst_md()->data_type, diff_src_md()->data_type)
&& set_default_formats_common()
&& attr()->has_default_values() && desc_.local_size % 2
&& check_format()
&& memory_desc_wrapper(diff_src_md())
== memory_desc_wrapper(diff_dst_md());
if (!ok) return status::unimplemented;
if (has_zero_dim_memory()) { return status::success; };
lrn_impl_.reset(new miopen_lrn_bwd_impl_t());
CHECK(lrn_impl_->init(this));
CHECK(init_ws());
if (!compare_ws(hint_fwd_pd_)) return status::unimplemented;
return status::success;
}
status_t init_ws() {
const size_t miopen_ws_size = lrn_impl_->get_workspace_size();
const size_t dst_size = memory_desc_wrapper(src_md()).size();
const size_t ws_size = miopen_ws_size + dst_size;
dims_t dims = {(dim_t)ws_size};
return memory_desc_init_by_tag(ws_md_, ws_size ? 1 : 0, dims,
data_type::u8, format_tag::a);
}
bool check_format() const {
return (memory_desc_wrapper(src_md()).matches_one_of_tag(
format_tag::a, format_tag::ab, format_tag::abc,
format_tag::abcd)
&& memory_desc_wrapper(diff_src_md())
.matches_one_of_tag(format_tag::a,
format_tag::ab, format_tag::abc,
format_tag::abcd)
&& memory_desc_wrapper(diff_dst_md())
.matches_one_of_tag(format_tag::a,
format_tag::ab, format_tag::abc,
format_tag::abcd));
}
std::shared_ptr<miopen_lrn_impl_base_t> lrn_impl_;
};
status_t execute(const exec_ctx_t &ctx) const override;
private:
const pd_t *pd() const { return (const pd_t *)primitive_t::pd().get(); }
};
} } } }
#endif