#ifndef GPU_AMD_MIOPEN_POOLING_IMPL_HPP
#define GPU_AMD_MIOPEN_POOLING_IMPL_HPP
#include "gpu/amd/sycl_hip_utils.hpp"
#include <miopen/miopen.h>
namespace dnnl {
namespace impl {
namespace gpu {
namespace amd {
struct miopen_pooling_impl_base_t {
virtual status_t init(pooling_pd_t *pd) = 0;
virtual ~miopen_pooling_impl_base_t() {
for (size_t i = 0; i < NUM_IO; ++i) {
if (tensor_descs_[i]) {
MIOPEN_EXECUTE_FUNC_V(
miopenDestroyTensorDescriptor, tensor_descs_[i]);
}
}
if (pool_desc_) {
MIOPEN_EXECUTE_FUNC_V(miopenDestroyPoolingDescriptor, pool_desc_);
}
}
virtual void execute(
miopenHandle_t handle, void *x, void *y, void *ws) const
= 0;
size_t get_ws_size_miopen() const { return ws_size_miopen_; }
protected:
status_t init_common(pooling_pd_t *pd) {
ndims_ = std::max(4, pd->ndims());
kernel_ndims_ = ndims_ - 2;
if (kernel_ndims_ > 3) { return status::unimplemented; }
is_training_ = pd->desc()->prop_kind == prop_kind::forward_training;
bool is_fwd = pd->is_fwd();
auto src_md = is_fwd ? pd->src_md() : pd->diff_src_md();
auto dst_md = is_fwd ? pd->dst_md() : pd->diff_dst_md();
if (has_zero_dims(src_md->dims, pd->ndims())
|| has_zero_dims(dst_md->dims, pd->ndims())) {
return status::success;
}
if (is_training_) {
auto src_wrap = memory_desc_wrapper(src_md);
x_size_bytes_ = src_wrap.size();
}
convert_dims(src_md->padded_dims, dims_[src], pd->ndims());
convert_dims(dst_md->padded_dims, dims_[dst], pd->ndims());
convert_dims(src_md->format_desc.blocking.strides, strides_[src],
pd->ndims());
convert_dims(dst_md->format_desc.blocking.strides, strides_[dst],
pd->ndims());
convert_dims(pd->desc()->kernel, kernel_dims_, kernel_ndims_);
if (pd->ndims() == 3) {
dims_[src][3] = dims_[src][2];
dims_[src][2] = 1;
strides_[src][2] = dims_[src][3];
strides_[src][3] = 1;
dims_[dst][3] = dims_[dst][2];
dims_[dst][2] = 1;
strides_[dst][2] = dims_[dst][3];
strides_[dst][3] = 1;
kernel_dims_[1] = kernel_dims_[0];
kernel_dims_[0] = 1;
}
if (ndims_ == 4) {
kernel_padding_[0] = static_cast<int>(pd->padT());
kernel_padding_[1] = static_cast<int>(pd->padL());
kernel_strides_[0] = static_cast<int>(pd->KSH());
kernel_strides_[1] = static_cast<int>(pd->KSW());
} else {
kernel_padding_[0] = static_cast<int>(pd->padFront());
kernel_padding_[1] = static_cast<int>(pd->padT());
kernel_padding_[2] = static_cast<int>(pd->padL());
kernel_strides_[0] = static_cast<int>(pd->KSD());
kernel_strides_[1] = static_cast<int>(pd->KSH());
kernel_strides_[2] = static_cast<int>(pd->KSW());
}
CHECK(convert_data_type(src_md, &data_types_[src]));
CHECK(convert_data_type(dst_md, &data_types_[dst]));
CHECK(convert_alg_kind(pd->desc()->alg_kind, &pool_mode_));
CHECK(create_and_set_tensor_descriptor(&tensor_descs_[src],
data_types_[src], ndims_, dims_[src], strides_[src]));
CHECK(create_and_set_tensor_descriptor(&tensor_descs_[dst],
data_types_[dst], ndims_, dims_[dst], strides_[dst]));
CHECK(create_and_set_pooling_descriptor(pd));
return status::success;
}
status_t create_and_set_pooling_descriptor(const pooling_pd_t *pd) {
CHECK(MIOPEN_EXECUTE_FUNC_S(
miopenCreatePoolingDescriptor, &pool_desc_));
CHECK(MIOPEN_EXECUTE_FUNC_S(miopenSetNdPoolingDescriptor, pool_desc_,
pool_mode_, kernel_ndims_, kernel_dims_, kernel_padding_,
kernel_strides_));
miopenSetPoolingIndexType(pool_desc_, index_type);
miopenSetPoolingWorkSpaceIndexMode(pool_desc_, workspace_mode);
return status::success;
}
status_t convert_alg_kind(
alg_kind_t alg_kind, miopenPoolingMode_t *miopen_alg_kind) const {
switch (alg_kind) {
case alg_kind::pooling_max:
*miopen_alg_kind = miopenPoolingMax;
break;
case alg_kind::pooling_avg_include_padding:
*miopen_alg_kind = miopenPoolingAverageInclusive;
break;
case alg_kind::pooling_avg_exclude_padding:
*miopen_alg_kind = miopenPoolingAverage;
break;
default: return status::unimplemented;
}
return status::success;
}
enum io { src = 0, dst, NUM_IO };
miopenDataType_t data_types_[NUM_IO];
miopenTensorDescriptor_t tensor_descs_[NUM_IO] = {};
miopenPoolingDescriptor_t pool_desc_;
miopenPoolingMode_t pool_mode_ = miopenPoolingMode_t::miopenPoolingMax;
miopenIndexType_t index_type = miopenIndexType_t::miopenIndexUint32;
miopenPoolingWorkspaceIndexMode_t workspace_mode
= miopenPoolingWorkspaceIndexMode_t::
miopenPoolingWorkspaceIndexImage;
int dims_[NUM_IO][DNNL_MAX_NDIMS];
int strides_[NUM_IO][DNNL_MAX_NDIMS];
int kernel_dims_[DNNL_MAX_NDIMS];
int kernel_padding_[DNNL_MAX_NDIMS];
int kernel_strides_[DNNL_MAX_NDIMS];
const float alpha_ = 1.f, beta_ = 0.f;
int ndims_, kernel_ndims_;
bool is_training_ = false;
size_t ws_size_miopen_ = 0;
size_t x_size_bytes_ = 0;
};
struct miopen_pooling_fwd_impl_t : public miopen_pooling_impl_base_t {
bool do_backward = false;
status_t init(pooling_pd_t *pd) override {
CHECK(init_common(pd));
if (is_training_) {
do_backward = true;
MIOPEN_EXECUTE_FUNC(miopenPoolingGetWorkSpaceSizeV2, pool_desc_,
tensor_descs_[dst], &ws_size_miopen_);
}
return status::success;
}
void execute(
miopenHandle_t handle, void *x, void *y, void *ws) const override {
void *ws_miopen = is_training_ ? ws : nullptr;
MIOPEN_EXECUTE_FUNC(miopenPoolingForward, handle, pool_desc_, &alpha_,
tensor_descs_[src], x, &beta_, tensor_descs_[dst], y,
do_backward, ws_miopen, ws_size_miopen_);
if (is_training_) {
void *ws_x = (uint8_t *)ws_miopen + ws_size_miopen_;
void *ws_y = (uint8_t *)ws_x + x_size_bytes_;
int alpha2 = 0;
miopenTensorOp_t tensorOp = miopenTensorOpAdd;
miopenOpTensor(handle, tensorOp, &alpha_, tensor_descs_[src], ws_x,
&alpha2, tensor_descs_[src], x, &beta_, tensor_descs_[src],
ws_x);
miopenOpTensor(handle, tensorOp, &alpha_, tensor_descs_[dst], ws_y,
&alpha2, tensor_descs_[dst], y, &beta_, tensor_descs_[dst],
ws_y);
}
}
};
struct miopen_pooling_bwd_impl_t : public miopen_pooling_impl_base_t {
status_t init(pooling_pd_t *pd) override {
CHECK(init_common(pd));
MIOPEN_EXECUTE_FUNC(miopenPoolingGetWorkSpaceSizeV2, pool_desc_,
tensor_descs_[dst], &ws_size_miopen_);
return status::success;
}
void execute(miopenHandle_t handle, void *dx, void *dy,
void *ws) const override {
void *ws_miopen = ws;
void *ws_x = (uint8_t *)ws + ws_size_miopen_;
void *ws_y = (uint8_t *)ws_x + x_size_bytes_;
MIOPEN_EXECUTE_FUNC(miopenPoolingBackward, handle, pool_desc_, &alpha_,
tensor_descs_[dst], ws_y, tensor_descs_[dst], dy,
tensor_descs_[src], ws_x, &beta_, tensor_descs_[src], dx,
ws_miopen);
}
};
} } } }
#endif