#ifndef CPU_RNN_CPU_RNN_PD_HPP
#define CPU_RNN_CPU_RNN_PD_HPP
#include "common/c_types_map.hpp"
#include "common/nstl.hpp"
#include "common/rnn_pd.hpp"
#include "common/type_helpers.hpp"
#include "common/utils.hpp"
#include "cpu/cpu_engine.hpp"
#include "cpu/rnn/rnn_utils.hpp"
namespace dnnl {
namespace impl {
namespace cpu {
struct cpu_rnn_fwd_pd_t : public rnn_fwd_pd_t {
using rnn_fwd_pd_t::rnn_fwd_pd_t;
protected:
status_t set_default_params() {
using namespace format_tag;
if (src_layer_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(src_layer_md_, tnc));
if (dst_layer_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(dst_layer_md_, tnc));
if (is_augru()) {
if (augru_attention_md().format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(augru_attention_md(), tnc));
}
if (with_src_iter() && src_iter_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(src_iter_md_, ldnc));
if (with_src_iter_c() && src_iter_c_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(src_iter_c_md_, ldnc));
if (is_lstm_peephole()
&& weights_peephole_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(weights_peephole_md_, ldgo));
if (with_bias() && bias_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(bias_md_, ldgo));
if (with_dst_iter() && dst_iter_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(dst_iter_md_, ldnc));
if (with_dst_iter_c() && dst_iter_c_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(dst_iter_c_md_, ldnc));
return status::success;
}
status_t check_layout_consistency(bool is_brgemm) {
using namespace format_tag;
using namespace data_type;
using namespace types;
const auto is_blocked = [&](const memory_desc_t &md, int ndims,
bool require_last_dim_contiguous) {
return md.format_kind == format_kind::blocked && md.ndims == ndims
&& IMPLICATION(require_last_dim_contiguous,
md.format_desc.blocking.strides[md.ndims - 1] == 1);
};
bool ok = true;
ok = ok && is_blocked(src_layer_md_, 3, true)
&& is_blocked(dst_layer_md_, 3, true);
ok = ok
&& IMPLICATION(!is_zero_md(&src_iter_md_),
is_blocked(src_iter_md_, 4, true))
&& IMPLICATION(!is_zero_md(&src_iter_c_md_),
is_blocked(src_iter_c_md_, 4, true))
&& IMPLICATION(!is_zero_md(&dst_iter_md_),
is_blocked(dst_iter_md_, 4, true))
&& IMPLICATION(!is_zero_md(&dst_iter_c_md_),
is_blocked(dst_iter_c_md_, 4, true));
if (weights_layer_md_.format_kind == format_kind::rnn_packed)
ok = ok
&& (weights_layer_md_.format_desc.rnn_packed_desc.format
== rnn_packed_memory_format_t::ldigo_p);
else
ok = ok
&& (rnn_utils::is_ldigo(&weights_layer_md_)
|| rnn_utils::is_ldigo_blocked(&weights_layer_md_));
if (weights_iter_md_.format_kind == format_kind::rnn_packed)
ok = ok
&& (weights_iter_md_.format_desc.rnn_packed_desc.format
== rnn_packed_memory_format_t::ldigo_p);
else
ok = ok
&& (rnn_utils::is_ldigo(&weights_iter_md_)
|| rnn_utils::is_ldigo_blocked(&weights_iter_md_));
ok = ok
&& IMPLICATION(is_lstm_peephole(),
memory_desc_matches_tag(weights_peephole_md_, ldgo));
if (is_lstm_projection()) {
if (weights_projection_md_.format_kind == format_kind::rnn_packed)
ok = ok
&& (weights_projection_md_.format_desc.rnn_packed_desc
.format
== rnn_packed_memory_format_t::ldio_p);
else
ok = ok
&& (rnn_utils::is_ldio(&weights_projection_md_)
|| rnn_utils::is_ldio_blocked(
&weights_projection_md_));
}
ok = ok
&& IMPLICATION(
with_bias(), memory_desc_matches_tag(bias_md_, ldgo));
const data_type_t weights_iter_dt = weights_iter_md_.data_type;
const data_type_t weights_layer_dt = weights_layer_md_.data_type;
if (!rnn_utils::is_ldigo_blocked(&weights_iter_md_))
ok = ok
&& IMPLICATION(weights_iter_dt == s8,
weights_iter_md_.format_kind
== format_kind::rnn_packed);
if (!rnn_utils::is_ldigo_blocked(&weights_layer_md_))
ok = ok
&& IMPLICATION(weights_layer_dt == s8,
weights_layer_md_.format_kind
== format_kind::rnn_packed);
return ok ? status::success : status::unimplemented;
}
};
struct cpu_rnn_bwd_pd_t : public rnn_bwd_pd_t {
using rnn_bwd_pd_t::rnn_bwd_pd_t;
protected:
status_t set_default_params() {
using namespace format_tag;
if (src_layer_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(src_layer_md_, tnc));
if (dst_layer_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(dst_layer_md_, tnc));
if (is_augru()) {
if (augru_attention_md().format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(augru_attention_md(), tnc));
if (diff_augru_attention_md().format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(diff_augru_attention_md(), tnc));
}
if (diff_src_layer_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(diff_src_layer_md_, tnc));
if (diff_weights_layer_md_.format_kind == format_kind::any) {
CHECK(memory_desc_init_by_tag(diff_weights_layer_md_, ldigo));
CHECK(rnn_utils::set_good_strides(diff_weights_layer_md_, ldigo));
}
if (diff_weights_iter_md_.format_kind == format_kind::any) {
CHECK(memory_desc_init_by_tag(diff_weights_iter_md_, ldigo));
CHECK(rnn_utils::set_good_strides(diff_weights_iter_md_, ldigo));
}
if (diff_dst_layer_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(diff_dst_layer_md_, tnc));
if (with_src_iter() && src_iter_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(src_iter_md_, ldnc));
if (with_src_iter_c() && src_iter_c_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(src_iter_c_md_, ldnc));
if (is_lstm_peephole()
&& weights_peephole_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(weights_peephole_md_, ldgo));
if (is_lstm_projection()
&& weights_projection_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(weights_projection_md_, ldoi));
if (with_bias() && bias_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(bias_md_, ldgo));
if (with_dst_iter() && dst_iter_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(dst_iter_md_, ldnc));
if (with_dst_iter_c() && dst_iter_c_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(dst_iter_c_md_, ldnc));
if (with_src_iter()
&& diff_src_iter_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(diff_src_iter_md_, ldnc));
if (with_src_iter_c()
&& diff_src_iter_c_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(diff_src_iter_c_md_, ldnc));
if (is_lstm_peephole()
&& diff_weights_peephole_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(diff_weights_peephole_md_, ldgo));
if (is_lstm_projection()
&& diff_weights_projection_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(diff_weights_projection_md_, ldio));
if (with_bias() && diff_bias_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(diff_bias_md_, ldgo));
if (with_dst_iter()
&& diff_dst_iter_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(diff_dst_iter_md_, ldnc));
if (with_dst_iter_c()
&& diff_dst_iter_c_md_.format_kind == format_kind::any)
CHECK(memory_desc_init_by_tag(diff_dst_iter_c_md_, ldnc));
return status::success;
}
status_t check_layout_consistency(bool is_brgemm) {
using namespace format_tag;
using namespace types;
const auto is_blocked = [&](const memory_desc_t &md, int ndims,
bool require_last_dim_contiguous) {
return md.format_kind == format_kind::blocked && md.ndims == ndims
&& IMPLICATION(require_last_dim_contiguous,
md.format_desc.blocking.strides[md.ndims - 1] == 1);
};
bool ok = true;
ok = ok && is_blocked(src_layer_md_, 3, true)
&& is_blocked(dst_layer_md_, 3, true);
ok = ok
&& IMPLICATION(!is_zero_md(&src_iter_md_),
is_blocked(src_iter_md_, 4, true))
&& IMPLICATION(!is_zero_md(&src_iter_c_md_),
is_blocked(src_iter_c_md_, 4, true))
&& IMPLICATION(!is_zero_md(&dst_iter_md_),
is_blocked(dst_iter_md_, 4, true))
&& IMPLICATION(!is_zero_md(&dst_iter_c_md_),
is_blocked(dst_iter_c_md_, 4, true));
const auto check_weights_consistency
= [&](const memory_desc_t &weights_md) {
if (weights_md.format_kind == format_kind::rnn_packed)
return ok
&& weights_md.format_desc.rnn_packed_desc.format
== rnn_packed_memory_format_t::ldgoi_p;
else if (is_brgemm)
return ok && rnn_utils::is_ldgoi_blocked(&weights_md);
else
return ok && rnn_utils::is_ldgoi(&weights_md);
};
ok = check_weights_consistency(weights_layer_md_);
ok = check_weights_consistency(weights_iter_md_);
ok = ok
&& IMPLICATION(is_augru(),
memory_desc_matches_tag(augru_attention_md(), tnc));
ok = ok
&& IMPLICATION(is_lstm_peephole(),
memory_desc_matches_tag(weights_peephole_md_, ldgo));
ok = ok
&& IMPLICATION(is_lstm_projection(),
memory_desc_matches_tag(weights_projection_md_, ldoi));
ok = ok
&& IMPLICATION(
with_bias(), memory_desc_matches_tag(bias_md_, ldgo));
ok = ok && is_blocked(diff_src_layer_md_, 3, true)
&& is_blocked(diff_dst_layer_md_, 3, true);
ok = ok
&& IMPLICATION(!is_zero_md(&diff_src_iter_md_),
is_blocked(diff_src_iter_md_, 4, true))
&& IMPLICATION(!is_zero_md(&diff_src_iter_c_md_),
is_blocked(diff_src_iter_c_md_, 4, true))
&& IMPLICATION(!is_zero_md(&diff_dst_iter_md_),
is_blocked(diff_dst_iter_md_, 4, true))
&& IMPLICATION(!is_zero_md(&diff_dst_iter_c_md_),
is_blocked(diff_dst_iter_c_md_, 4, true));
ok = ok
&& IMPLICATION(is_augru(),
memory_desc_matches_tag(
diff_augru_attention_md(), tnc));
ok = ok && rnn_utils::is_ldigo(&diff_weights_layer_md_)
&& rnn_utils::is_ldigo(&diff_weights_iter_md_);
ok = ok
&& IMPLICATION(is_lstm_peephole()
&& !is_zero_md(&diff_weights_peephole_md_),
memory_desc_matches_tag(
diff_weights_peephole_md_, ldgo));
ok = ok
&& IMPLICATION(!is_zero_md(&diff_weights_projection_md_),
memory_desc_matches_tag(
diff_weights_projection_md_, ldio));
ok = ok
&& IMPLICATION(!is_zero_md(&diff_bias_md_),
memory_desc_matches_tag(diff_bias_md_, ldgo));
return ok ? status::success : status::unimplemented;
}
};
} } }
#endif