#ifndef CPU_RV64_RVV_SOFTMAX_HPP
#define CPU_RV64_RVV_SOFTMAX_HPP
#include <memory>
#include "common/dnnl_thread.hpp"
#include "common/memory_tracking.hpp"
#include "common/primitive.hpp"
#include "cpu/cpu_softmax_pd.hpp"
#include "cpu/rv64/cpu_isa_traits.hpp"
#include "cpu/rv64/jit_rvv_softmax_affine_kernel.hpp"
namespace dnnl {
namespace impl {
namespace cpu {
namespace rv64 {
struct rvv_softmax_conf_t {
data_type_t data_type;
dim_t inner_size;
dim_t axis_size;
dim_t outer_size;
bool is_logsoftmax;
};
struct rvv_softmax_fwd_t : public primitive_t {
struct pd_t : public cpu_softmax_fwd_pd_t {
using cpu_softmax_fwd_pd_t::cpu_softmax_fwd_pd_t;
DECLARE_COMMON_PD_T("RISCV64GCV", rvv_softmax_fwd_t);
rvv_softmax_conf_t rsp_;
bool use_jit_ = false;
status_t init(engine_t *engine) {
UNUSED(engine);
VDISPATCH_SOFTMAX(set_default_formats() == status::success,
VERBOSE_UNSUPPORTED_TAG);
VDISPATCH_SOFTMAX(
attr()->has_default_values(), VERBOSE_UNSUPPORTED_ATTR);
VDISPATCH_SOFTMAX(!has_zero_dim_memory(), VERBOSE_EMPTY_TENSOR, "");
const memory_desc_wrapper src_d(src_md());
const memory_desc_wrapper dst_d(dst_md());
rsp_.is_logsoftmax = is_logsoftmax();
rsp_.data_type = src_md()->data_type;
rsp_.inner_size = src_d.blocking_desc().strides[axis()];
rsp_.axis_size = axis_size();
rsp_.outer_size
= src_d.nelems(true) / (rsp_.inner_size * axis_size(true));
const bool is_f16 = src_md()->data_type == data_type::f16;
VDISPATCH_SOFTMAX(utils::one_of(src_md()->data_type, data_type::f32,
data_type::f16),
VERBOSE_UNSUPPORTED_DT);
VDISPATCH_SOFTMAX(src_md()->data_type == dst_md()->data_type,
VERBOSE_UNSUPPORTED_DT);
VDISPATCH_SOFTMAX(mayiuse(v), VERBOSE_UNSUPPORTED_ISA);
if (is_f16) {
VDISPATCH_SOFTMAX(mayiuse(zvfh), VERBOSE_UNSUPPORTED_ISA);
}
VDISPATCH_SOFTMAX(
platform::has_data_type_support(src_md()->data_type),
VERBOSE_UNSUPPORTED_DT);
VDISPATCH_SOFTMAX(
check_layouts(src_d, dst_d), VERBOSE_UNSUPPORTED_TAG);
#if defined(XBYAK_RISCV_V) && XBYAK_RISCV_V == 1
use_jit_ = rsp_.data_type == data_type::f32;
#else
use_jit_ = false;
#endif
init_scratchpad();
return status::success;
}
bool check_layouts(const memory_desc_wrapper &src_d,
const memory_desc_wrapper &dst_d) const {
if (!src_d.is_plain() || !dst_d.is_plain()) return false;
if (!src_d.is_dense(true) || !dst_d.is_dense(true)) return false;
if (!(src_d == dst_d)) return false;
return true;
}
void init_scratchpad() {
auto scratchpad = scratchpad_registry().registrar();
nthr_ = rsp_.inner_size > 1 ? dnnl_get_max_threads() : 1;
const size_t dt_size = types::data_type_size(rsp_.data_type);
if (rsp_.inner_size > 1) {
scratchpad.template book<char>(
memory_tracking::names::key_softmax_interim_store,
static_cast<size_t>(axis_size(true)) * dt_size
* static_cast<size_t>(nthr_));
}
}
int nthr_ = 0;
};
rvv_softmax_fwd_t(const pd_t *apd);
status_t execute(const exec_ctx_t &ctx) const override {
return execute_forward(ctx);
}
private:
status_t execute_forward(const exec_ctx_t &ctx) const;
const pd_t *pd() const { return (const pd_t *)primitive_t::pd().get(); }
std::unique_ptr<jit_rvv_softmax_affine_kernel_t> affine_kernel_;
};
} } } }
#endif