#ifndef CPU_SIMPLE_SUM_HPP
#define CPU_SIMPLE_SUM_HPP
#include "common/dnnl_thread.hpp"
#include "common/primitive.hpp"
#include "common/type_helpers.hpp"
#include "cpu/cpu_sum_pd.hpp"
#include "cpu/platform.hpp"
namespace dnnl {
namespace impl {
namespace cpu {
struct sum_xf16_params_t {
dim_t ws_cvt_elements_per_thread_;
dim_t ws_acc_elements_per_thread_;
dim_t ws_elements_per_thread_;
dim_t acc_loop_step_;
};
template <data_type_t src_data_type, data_type_t dst_data_type = src_data_type>
struct simple_sum_t : public primitive_t {
struct pd_t : public cpu_sum_pd_t {
using cpu_sum_pd_t::cpu_sum_pd_t;
DECLARE_SUM_PD_T("simple:any", simple_sum_t);
status_t init(engine_t *engine) {
const int n = n_inputs();
VDISPATCH_SUM(platform::has_data_type_support(src_data_type),
VERBOSE_UNSUPPORTED_DT);
VDISPATCH_SUM(platform::has_data_type_support(dst_data_type),
VERBOSE_UNSUPPORTED_DT);
VDISPATCH_SUM(cpu_sum_pd_t::init(engine) == status::success,
VERBOSE_BAD_ENGINE_KIND);
VDISPATCH_SUM(n <= max_num_arrs,
"number of inputs exceed max number of arrays");
const memory_desc_wrapper o_d(dst_md());
VDISPATCH_SUM(o_d.data_type() == dst_data_type,
VERBOSE_INCONSISTENT_DT, "o_d", "dst");
VDISPATCH_SUM(o_d.is_dense(), VERBOSE_UNSUPPORTED_SPARSE_CFG);
for (int i = 0; i < n; ++i) {
const memory_desc_wrapper i_d(src_md(i));
VDISPATCH_SUM(
utils::everyone_is(src_data_type, i_d.data_type()),
VERBOSE_UNSUPPORTED_DT);
VDISPATCH_SUM(o_d.similar_to(i_d, true, false, 0),
VERBOSE_INCONSISTENT_MDS, "o_d", "i_d");
VDISPATCH_SUM(i_d.is_dense(), VERBOSE_UNSUPPORTED_SPARSE_CFG);
}
nthr_ = dnnl_get_max_threads();
compute_blocking();
init_scratchpad();
return status::success;
}
int nthr_ = 1;
sum_xf16_params_t xf16_params_;
dim_t block_size_ = 0, nelems_ = 0, blocks_number_ = 0, tail_ = 0;
private:
void compute_blocking() {
const int block_size_bytes
= utils::one_of(
src_data_type, data_type::bf16, data_type::f16)
? 16 * platform::get_cache_line_size()
: platform::get_per_core_cache_size(1) / 2;
block_size_ = block_size_bytes / (int)sizeof(src_data_type);
const memory_desc_wrapper o_d(dst_md());
nelems_ = o_d.nelems();
blocks_number_ = nelems_ / block_size_;
tail_ = nelems_ % block_size_;
}
void init_scratchpad() {
if (utils::one_of(src_data_type, data_type::bf16, data_type::f16)) {
const bool is_dst_xf16 = utils::one_of(
dst_data_type, data_type::bf16, data_type::f16);
xf16_params_.ws_cvt_elements_per_thread_
= platform::get_cache_line_size()
/ (int)sizeof(acc_data_t);
xf16_params_.ws_acc_elements_per_thread_ = is_dst_xf16
? xf16_params_.ws_cvt_elements_per_thread_
: 0;
xf16_params_.acc_loop_step_ = is_dst_xf16
? xf16_params_.ws_cvt_elements_per_thread_
: 1;
xf16_params_.ws_elements_per_thread_
= xf16_params_.ws_cvt_elements_per_thread_
+ xf16_params_.ws_acc_elements_per_thread_;
const dim_t cvt_buf_sz
= xf16_params_.ws_elements_per_thread_ * nthr_;
auto scratchpad = scratchpad_registry().registrar();
scratchpad.template book<acc_data_t>(
memory_tracking::names::key_sum_srcs_cvt, cvt_buf_sz);
}
}
};
simple_sum_t(const pd_t *apd) : primitive_t(apd) {}
status_t execute(const exec_ctx_t &ctx) const override;
enum { max_num_arrs = 16 };
using src_data_t = typename prec_traits_t<src_data_type>::type;
using dst_data_t = typename prec_traits_t<dst_data_type>::type;
using acc_data_t = typename prec_traits_t<data_type::f32>::type;
private:
const pd_t *pd() const { return (const pd_t *)primitive_t::pd().get(); }
};
} } }
#endif