#include "common/bfloat16.hpp"
#include "cpu/rnn/ref_rnn.hpp"
#if DNNL_X64
#include <cassert>
#include <functional>
#include "cpu/x64/rnn/brgemm_cell_common_bwd.hpp"
#include "cpu/x64/rnn/brgemm_cell_common_fwd.hpp"
#include "cpu/x64/rnn/brgemm_cell_common_reorders.hpp"
#include "cpu/x64/rnn/brgemm_cell_common_utils.hpp"
#endif
namespace dnnl {
namespace impl {
namespace cpu {
using namespace rnn_utils;
using namespace dnnl::impl::utils;
#if DNNL_X64
using namespace dnnl::impl::cpu::x64;
#endif
template <data_type_t src_type, data_type_t weights_type, data_type_t acc_type>
rnn_merged_layer_execution_sig((
ref_rnn_fwd_t<src_type, weights_type, acc_type>::merged_layer_brgemm)) {
#if DNNL_X64
using brgemm_merged_layer_t = x64::brgemm_merged_layer_t<src_iter_t,
weights_t, scratch_t, gemm_acc_t>;
const brgemm_merged_layer_t layer_calc(this->rnn_brgemm_, rnn,
cell_position, src_layer_, w_layer_[0], scratch_gates_,
amx_scratchpad, addr_batch_global);
layer_calc.execute();
#endif
return dnnl_success;
}
template rnn_merged_layer_execution_sig(ref_rnn_fwd_f32_t::merged_layer_brgemm);
template rnn_merged_layer_execution_sig(
ref_rnn_fwd_bf16_t::merged_layer_brgemm);
template rnn_merged_layer_execution_sig(ref_rnn_fwd_f16_t::merged_layer_brgemm);
template rnn_merged_layer_execution_sig(
ref_rnn_fwd_u8s8_t::merged_layer_brgemm);
template rnn_merged_layer_execution_sig(
ref_rnn_fwd_s8s8_t::merged_layer_brgemm);
template <data_type_t src_type, data_type_t weights_type, data_type_t acc_type>
rnn_cell_execution_sig((ref_rnn_fwd_t<src_type, weights_type,
acc_type>::cell_execution_brgemm)) {
#if DNNL_X64
const auto weights_scales = this->pd_->attr()->rnn_weights_qparams_.scales_;
const int mask = this->pd()->attr()->rnn_weights_qparams_.mask_;
const auto dst_postgemm = rnn.is_lstm_projection ? proj_ht_ : dst_layer_;
const auto dst_iter_postgemm = rnn.is_lstm_projection ? nullptr : dst_iter_;
const auto LDDl = rnn.dst_layer_ld(cell_position);
const auto LDDi = rnn.dst_iter_ld(cell_position);
const auto LDDic = rnn.dst_iter_c_ld(cell_position);
const auto LDAic = rnn.src_iter_c_ld(cell_position);
using brgemm_dst_layer_iter_t = x64::brgemm_dst_layer_iter_t<src_iter_t,
weights_t, scratch_t, gemm_acc_t>;
typename brgemm_dst_layer_iter_t::postgemm_fused_t fused_postgemm;
if (!rnn.unfused_post_gemm) {
fused_postgemm
= [&](dim_t m, dim_t n, dim_t nb_i, const src_iter_t *Ai_m,
scratch_t *C_n, scratch_t *C_cell_n, int block_step) {
const auto Dpg_n = (dst_postgemm != nullptr)
? dst_postgemm + m * LDDl + n
: nullptr;
const auto Di_n = (dst_iter_postgemm != nullptr)
? dst_iter_postgemm + m * LDDi + n
: nullptr;
const auto Dic_n = (dst_iter_c_ != nullptr)
? inc_ptr(dst_iter_c_, rnn.dst_iter_c_dt, m * LDDic + n)
: nullptr;
const auto curr_ws_gates_
= ws_gates_ + (m * rnn.ws_gates_ld) + nb_i * rnn.n_block;
const float *weights_peephole_n = weights_peephole_
? weights_peephole_ + n
: weights_peephole_;
auto weights_scales_n = weights_scales + (mask ? n : 0);
const auto Aic_n
= inc_ptr(src_iter_c_, rnn.src_iter_c_dt, m * LDAic + n);
const auto bias_n = inc_ptr(bias_[0], rnn.bias_dt, n);
this->rnn_postgemm_->execute(rnn, cell_position, curr_ws_gates_,
C_n, augru_attention_, Dpg_n, Dic_n, Ai_m, Aic_n,
diff_src_layer_, diff_augru_attention_, diff_src_iter_,
diff_src_iter_c_, diff_dst_layer_, diff_dst_iter_,
diff_dst_iter_c_, weights_peephole_n, bias_n, ws_grid_,
C_cell_n, Di_n, weights_scales_n, block_step);
};
}
if (rnn.is_orig_gru) {
using brgemm_gru_t = x64::brgemm_gru_t<src_iter_t, weights_t, scratch_t,
gemm_acc_t>;
typename brgemm_gru_t::postgemm_fused_t fused_postgemm_gru_part1,
fused_postgemm_gru_part2;
if (!rnn.unfused_post_gemm) {
fused_postgemm_gru_part1
= [&](dim_t m, dim_t n, dim_t nb_i, const src_iter_t *Ai_m,
scratch_t *C_gates_n, scratch_t *C_cell_n,
int block_step) {
const auto Dpg_n = (dst_postgemm != nullptr)
? dst_postgemm + m * LDDl + n
: nullptr;
const auto Di_n = (dst_iter_postgemm != nullptr)
? dst_iter_postgemm + m * LDDi + n
: nullptr;
const auto Dic_n = (dst_iter_c_ != nullptr)
? inc_ptr(dst_iter_c_, rnn.dst_iter_c_dt, m * LDDic + n)
: nullptr;
const auto curr_ws_gates_ = ws_gates_ + (m * rnn.ws_gates_ld)
+ nb_i * rnn.n_block;
const auto Aic_n = inc_ptr(
src_iter_c_, rnn.src_iter_c_dt, m * LDAic + n);
const auto bias_n = inc_ptr(bias_[0], rnn.bias_dt, n);
auto weights_scales_n = weights_scales + (mask ? n : 0);
this->rnn_postgemm_->execute(rnn, cell_position, curr_ws_gates_,
C_gates_n, augru_attention_, Dpg_n, Dic_n, Ai_m, Aic_n,
diff_src_layer_, diff_augru_attention_, diff_src_iter_,
diff_src_iter_c_, diff_dst_layer_, diff_dst_iter_,
nullptr, nullptr, bias_n, ws_grid_, C_cell_n, Di_n,
weights_scales_n, block_step);
};
fused_postgemm_gru_part2
= [&](dim_t m, dim_t n, dim_t nb_i, const src_iter_t *Ai_m,
scratch_t *C_gates_n, scratch_t *C_cell_n,
int block_step) {
const auto Dpg_n = (dst_postgemm != nullptr)
? dst_postgemm + m * LDDl + n
: nullptr;
const auto Di_n = (dst_iter_postgemm != nullptr)
? dst_iter_postgemm + m * LDDi + n
: nullptr;
const auto Dic_n = (dst_iter_c_ != nullptr)
? inc_ptr(dst_iter_c_, rnn.dst_iter_c_dt, m * LDDic + n)
: nullptr;
const auto curr_ws_gates_ = ws_gates_ + (m * rnn.ws_gates_ld)
+ nb_i * rnn.n_block;
const auto Aic_n = inc_ptr(
src_iter_c_, rnn.src_iter_c_dt, m * LDAic + n);
const auto bias_n = inc_ptr(bias_[0], rnn.bias_dt, n);
auto weights_scales_n = weights_scales + (mask ? n : 0);
this->rnn_postgemm_->execute_part2(rnn, cell_position,
curr_ws_gates_, C_gates_n, augru_attention_, Dpg_n,
Dic_n, Ai_m, Aic_n, diff_src_layer_,
diff_augru_attention_, diff_src_iter_, diff_src_iter_c_,
diff_dst_layer_, diff_dst_iter_, nullptr, nullptr,
bias_n, ws_grid_, C_cell_n, Di_n, weights_scales_n,
block_step);
};
}
const brgemm_gru_t dst_calc(this->rnn_brgemm_, rnn, cell_position,
src_iter_, src_layer_, w_iter_[0], w_iter_[1], w_layer_[0],
dst_postgemm, scratch_gates_, scratch_cell_, amx_scratchpad,
addr_batch_global, fused_postgemm_gru_part1,
fused_postgemm_gru_part2);
dst_calc.execute();
} else {
const brgemm_dst_layer_iter_t dst_calc(this->rnn_brgemm_, rnn,
cell_position, src_iter_, src_layer_, w_iter_[0], w_layer_[0],
scratch_gates_, scratch_cell_, amx_scratchpad,
addr_batch_global, fused_postgemm);
dst_calc.execute();
}
if (rnn.unfused_post_gemm) {
const auto wscales_postgemm
= this->pd_->attr()->rnn_weights_qparams_.scales_;
this->rnn_postgemm_->execute(rnn, cell_position, ws_gates_,
scratch_gates_, augru_attention_, dst_postgemm, dst_iter_c_,
src_iter_, src_iter_c_, diff_src_layer_, diff_augru_attention_,
diff_src_iter_, diff_src_iter_c_, diff_dst_layer_,
diff_dst_iter_, diff_dst_iter_c_, weights_peephole_, bias_[0],
ws_grid_, scratch_cell_, dst_iter_postgemm, wscales_postgemm,
rnn.dhc * sizeof(scratch_t));
}
if (rnn.is_lstm_projection) {
const auto wscales_proj_postgemm
= this->pd_->attr()->rnn_weights_projection_qparams_.scales_;
gemm_acc_t *const Cp = (rnn.dt_conf == all_f32)
? reinterpret_cast<gemm_acc_t *>(dst_layer_)
: scratch_gates_;
const int pLDDl = rnn.dst_layer_ld(cell_position, true);
const int pmask
= this->pd_->attr()->rnn_weights_projection_qparams_.mask_;
using brgemm_dst_proj_t
= x64::brgemm_dst_proj_t<ht_t, weights_t, gemm_acc_t>;
typename brgemm_dst_proj_t::postgemm_fused_t fused_postgemm_proj;
if (!rnn.unfused_post_gemm) {
fused_postgemm_proj
= [&](dim_t m, dim_t n, gemm_acc_t *Cp_n, int block_step) {
const auto weights_scales_n
= wscales_proj_postgemm + (pmask ? n : 0);
const auto Di_n = (dst_iter_ != nullptr)
? dst_iter_ + m * LDDi + n
: nullptr;
const auto Dl_n = (dst_layer_ != nullptr)
? dst_layer_ + m * pLDDl + n
: nullptr;
const auto Wp_comp_n = w_proj_comp + n;
this->rnn_postgemm_->execute_part2(rnn, cell_position, nullptr,
Cp_n, nullptr, Dl_n, nullptr, nullptr, Wp_comp_n,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, Di_n,
weights_scales_n, block_step);
};
}
const brgemm_dst_proj_t dst_proj_calc(this->rnn_brgemm_, rnn,
cell_position, proj_ht_, w_projection_[0], Cp, amx_scratchpad,
addr_batch_global, fused_postgemm_proj);
dst_proj_calc.execute();
if (rnn.unfused_post_gemm) {
this->rnn_postgemm_->execute_part2(rnn, cell_position, nullptr, Cp,
nullptr, dst_layer_, nullptr, nullptr, w_proj_comp, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, dst_iter_,
wscales_proj_postgemm, rnn.dlc * sizeof(dst_layer_t));
}
}
#endif
return dnnl_success;
}
template rnn_cell_execution_sig(ref_rnn_fwd_f32_t::cell_execution_brgemm);
template rnn_cell_execution_sig(ref_rnn_fwd_bf16_t::cell_execution_brgemm);
template rnn_cell_execution_sig(ref_rnn_fwd_f16_t::cell_execution_brgemm);
template rnn_cell_execution_sig(ref_rnn_fwd_u8s8_t::cell_execution_brgemm);
template rnn_cell_execution_sig(ref_rnn_fwd_s8s8_t::cell_execution_brgemm);
template <data_type_t src_type, data_type_t weights_type, data_type_t acc_type>
rnn_cell_execution_sig((ref_rnn_bwd_t<src_type, weights_type,
acc_type>::cell_execution_brgemm)) {
#if DNNL_X64
this->rnn_postgemm_->execute(rnn, cell_position, ws_gates_, scratch_gates_,
augru_attention_, dst_layer_, dst_iter_c_, src_iter_, src_iter_c_,
diff_src_layer_, diff_augru_attention_, diff_src_iter_,
diff_src_iter_c_, diff_dst_layer_, diff_dst_iter_, diff_dst_iter_c_,
weights_peephole_, bias_[0], ws_grid_, scratch_cell_, dst_iter_,
nullptr, 0);
using brgemm_diff_src_calc_t = x64::brgemm_diff_src_layer_iter_t<weights_t,
scratch_t, gemm_acc_t>;
using brgemm_diff_weights_calc_t
= x64::brgemm_diff_weights_layer_iter_t<src_layer_t, src_iter_t,
scratch_t, gemm_acc_t>;
const brgemm_diff_src_calc_t diff_src_calc(this->rnn_brgemm_, rnn,
cell_position, scratch_gates_, w_iter_[0], w_layer_[0],
diff_src_iter_, diff_src_layer_, amx_scratchpad, addr_batch_global);
const brgemm_diff_weights_calc_t diff_weights_calc(this->rnn_brgemm_, rnn,
cell_position, src_iter_, scratch_src_iter_, src_layer_,
scratch_src_layer_, scratch_gates_, scratch_gates_blocked_,
diff_w_iter_, diff_w_layer_, diff_bias_, amx_scratchpad,
addr_batch_global);
diff_src_calc.execute();
if (rnn.diff_wei_brgemm.global_transpose) {
const auto src_layer_ld = rnn.src_layer_ld(cell_position);
const auto src_iter_ld = rnn.src_iter_ld(cell_position);
const auto src_layer_ld_nb = rnn.layer_brgemm_desc(cell_position);
const auto src_iter_ld_nb = rnn.iter_brgemm_desc(cell_position);
const auto rnd_up_size = data_type_vnni_granularity(src_type);
const auto dst_ld = utils::rnd_up(rnn.mb, rnd_up_size);
const auto layer_transpose = src_layer_iter_transpose_t(src_layer_ld,
dst_ld, rnn.mb, rnn.slc,
this->rnn_brgemm_.kernel_transpose_layer_[src_layer_ld_nb]
.get());
const auto iter_transpose = src_layer_iter_transpose_t(src_iter_ld,
dst_ld, rnn.mb, rnn.sic,
this->rnn_brgemm_.kernel_transpose_iter_[src_iter_ld_nb].get());
layer_transpose.execute(src_layer_, scratch_src_layer_);
iter_transpose.execute(src_iter_, scratch_src_iter_);
}
diff_weights_calc.execute();
if (rnn.is_lstm_peephole) {
using brgemm_diff_wei_peep_t = x64::brgemm_diff_wei_peep_t<scratch_t>;
const brgemm_diff_wei_peep_t diff_wei_peep_calc(this->rnn_brgemm_, rnn,
cell_position, scratch_gates_, src_iter_c_, dst_iter_c_,
diff_weights_peephole_);
diff_wei_peep_calc.execute();
}
#endif
return dnnl_success;
}
template rnn_cell_execution_sig(ref_rnn_bwd_f32_t::cell_execution_brgemm);
template rnn_cell_execution_sig(ref_rnn_bwd_bf16_t::cell_execution_brgemm);
template rnn_cell_execution_sig(ref_rnn_bwd_f16_t::cell_execution_brgemm);
} } }