#ifndef GPU_INTEL_SUM_MANY_INPUTS_HPP
#define GPU_INTEL_SUM_MANY_INPUTS_HPP
#include "common/c_types_map.hpp"
#include "common/primitive.hpp"
#include "gpu/gpu_resource.hpp"
#include "gpu/intel/primitive.hpp"
#include "gpu/intel/primitive_conf.hpp"
#include "gpu/intel/sum/config.hpp"
namespace dnnl {
namespace impl {
namespace gpu {
namespace intel {
namespace sum {
struct many_inputs_t : public primitive_t {
using primitive_t::primitive_t;
struct pd_t : public sum::pd_t {
using sum::pd_t::pd_t;
DECLARE_SUM_PD_T("ocl:many_inputs", many_inputs_t);
status_t init(impl::engine_t *engine) {
const int n = n_inputs();
VDISPATCH_SUM_SC(sum::pd_t::init(engine), VERBOSE_BAD_ENGINE_KIND);
const memory_desc_wrapper o_d(dst_md());
for (int i = 0; i < n; ++i) {
const memory_desc_wrapper i_d(src_md(i));
VDISPATCH_SUM(i_d == o_d, VERBOSE_INCONSISTENT_DIM, "i_d", i,
"o_d", i);
}
VDISPATCH_SUM(scales()[0] == 1.0f, VERBOSE_UNSUPPORTED_SCALES_CFG);
return status::success;
}
};
status_t init(impl::engine_t *engine) override {
compute::kernel_ctx_t kernel_ctx;
const memory_desc_wrapper data_d(pd()->dst_md());
const memory_desc_wrapper data_s(pd()->src_md());
kernel_ctx.set_data_type(data_s.data_type());
kernel_ctx.require_stateless_addressing(pd()->has_large_buffers());
kernel_ctx.define_int("N_ELEMS", data_d.nelems(true));
const int num_arrs = pd()->n_inputs() - 1;
int N_INPUTS = (num_arrs) % max_num_arrs;
if (N_INPUTS == 0) { N_INPUTS = max_num_arrs; };
kernel_ctx.define_int("N_INPUTS", N_INPUTS);
kernel_ctx.define_int("MAX_N_INPUTS", max_num_arrs);
def_memory_desc_info(
kernel_ctx, memory_desc_info_t::create(data_d), "SRC");
def_memory_desc_info(
kernel_ctx, memory_desc_info_t::create(data_s), "DST");
std::vector<compute::kernel_t> kernels;
std::vector<const char *> kernel_names;
kernel_names.push_back("many_inputs_sum");
kernel_names.push_back("many_inputs_sum_batched");
CHECK(create_kernels(engine, &kernels, kernel_names, kernel_ctx));
kernel_ = kernels[0];
batched_kernel_ = kernels[1];
if (!kernel_ || !batched_kernel_) return status::runtime_error;
return status::success;
}
status_t init_res_storage(
impl::engine_t *engine, gpu_resource_t *r) const override {
const dim_t count = pd()->n_inputs();
const float *s_data = pd()->scales();
const size_t size = count * sizeof(float);
std::unique_ptr<memory_storage_t> scales;
memory_storage_t *scale = nullptr;
auto s = engine->create_memory_storage(&scale, size);
if (s != status::success) return s;
float *mapped_mem_storage = nullptr;
s = scale->map_data((void **)&mapped_mem_storage, nullptr, size);
if (s != status::success) return s;
utils::array_copy(mapped_mem_storage, s_data, count);
s = scale->unmap_data((void *)mapped_mem_storage, nullptr);
if (s != status::success) return s;
scales.reset(scale);
r->add_memory_storage(SCALES_, std::move(scales));
return status::success;
}
status_t execute(const exec_ctx_t &ctx) const override;
private:
enum { max_num_arrs = 16 };
enum { SCALES_ = 0 };
const pd_t *pd() const { return (const pd_t *)primitive_t::pd().get(); }
compute::kernel_t kernel_;
compute::kernel_t batched_kernel_;
};
} } } } }
#endif