mirror of
https://github.com/opencv/opencv.git
synced 2026-09-12 05:11:04 -05:00
dnn:rvv: implement RVV HAL kernels for max and average pooling
This commit is contained in:
@@ -18,12 +18,7 @@ target_include_directories(${HAL_LIB_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_SOURCE_DIR}/modules/core/include
|
||||
${CMAKE_SOURCE_DIR}/modules/imgproc/include
|
||||
${CMAKE_SOURCE_DIR}/modules/features/include
|
||||
${CMAKE_SOURCE_DIR}/modules/dnn/include
|
||||
# dnn's internal ConvState descriptor (src/layers/conv2_common.hpp) crosses the
|
||||
# HAL boundary as an opaque pointer; the dnn kernels cast it back here. See the
|
||||
# "descriptor ABI" discussion in the DNN HAL proposal.
|
||||
${CMAKE_SOURCE_DIR}/modules/dnn/src)
|
||||
${CMAKE_SOURCE_DIR}/modules/features/include)
|
||||
|
||||
set(RVV_HAL_FOUND TRUE CACHE INTERNAL "")
|
||||
set(RVV_HAL_VERSION "0.0.1" CACHE INTERNAL "")
|
||||
|
||||
@@ -9,27 +9,30 @@ namespace cv { namespace rvv_hal { namespace dnn {
|
||||
|
||||
#if CV_HAL_RVV_1P0_ENABLED
|
||||
|
||||
// `state` is an opaque pointer to the DNN engine's cv::dnn::ConvState descriptor.
|
||||
// It is passed as const void* on purpose: this header is pulled into every module
|
||||
// through the generated custom_hal.hpp, so it must not depend on internal dnn
|
||||
// headers. The implementations in src/dnn/ include conv2_common.hpp and cast back.
|
||||
//
|
||||
// Each hook computes only the block-plane range [task_start, task_end) of the
|
||||
// output tensor (blocked NCHWc, N*C1 planes of C0 channels); OpenCV owns the
|
||||
// parallel_for_ and never expects the HAL to spawn threads.
|
||||
// Blocked NCHWc pooling, CV_32F. The geometry crosses the boundary as a flat, stable
|
||||
// C argument list (no dnn types): C0 channel block; insize/outsize = the [3] input/output
|
||||
// spatial dims in a fixed Z,Y,X frame (unused leading dims = 1); strides[3]; pads[6]
|
||||
// (begin[0..2]+end[3..5]); inner[6] = the padding-free interior bounds; coordtab[ksize*3]
|
||||
// = per-tap (dz,dy,dx); ofstab[ksize] = per-tap flat input offset for the interior.
|
||||
// Each hook computes only the block-plane range [task_start, task_end) (N*C1 planes);
|
||||
// OpenCV owns the parallel_for_ and never expects the HAL to spawn threads.
|
||||
|
||||
/* ############ maxpool32f ############ */
|
||||
|
||||
int maxpool32f(const float* inp_data, float* out_data,
|
||||
const void* state, int task_start, int task_end);
|
||||
int maxpool32f(const float* inp_data, float* out_data, int C0,
|
||||
const int* insize, const int* outsize, const int* strides,
|
||||
const int* pads, const int* inner, const int* coordtab,
|
||||
const int* ofstab, int ksize, int task_start, int task_end);
|
||||
|
||||
#undef cv_hal_dnn_maxpool32f
|
||||
#define cv_hal_dnn_maxpool32f cv::rvv_hal::dnn::maxpool32f
|
||||
|
||||
/* ############ avgpool32f ############ */
|
||||
|
||||
int avgpool32f(const float* inp_data, float* out_data,
|
||||
const void* state, int count_include_pad,
|
||||
int avgpool32f(const float* inp_data, float* out_data, int C0,
|
||||
const int* insize, const int* outsize, const int* strides,
|
||||
const int* pads, const int* inner, const int* coordtab,
|
||||
const int* ofstab, int ksize, int count_include_pad,
|
||||
int task_start, int task_end);
|
||||
|
||||
#undef cv_hal_dnn_avgpool32f
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#if CV_HAL_RVV_1P0_ENABLED
|
||||
#include <cfloat>
|
||||
#include "layers/conv2_common.hpp" // cv::dnn::ConvState (opaque across the HAL boundary)
|
||||
#endif
|
||||
|
||||
namespace cv { namespace rvv_hal { namespace dnn {
|
||||
@@ -30,32 +29,22 @@ namespace cv { namespace rvv_hal { namespace dnn {
|
||||
// * stride-x > 1: pixels' tap data are strided; we fall back to processing C0
|
||||
// channels per vector, register-blocked 4 output columns at a time for ILP.
|
||||
|
||||
int maxpool32f(const float* inp_data, float* out_data,
|
||||
const void* state, int task_start, int task_end)
|
||||
int maxpool32f(const float* inp_data, float* out_data, int C0,
|
||||
const int* insize, const int* outsize, const int* strides,
|
||||
const int* pads, const int* inner, const int* coordtab,
|
||||
const int* ofstab, int ksize, int task_start, int task_end)
|
||||
{
|
||||
const cv::dnn::ConvState* cs = static_cast<const cv::dnn::ConvState*>(state);
|
||||
constexpr int MAX_POOL_DIMS = cv::dnn::ConvState::MAX_CONV_DIMS;
|
||||
if (cs->nspatialdims > MAX_POOL_DIMS)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
const int sdims = cs->nspatialdims;
|
||||
const int C0 = cs->inpshape.back();
|
||||
const int Di = sdims > 2 ? cs->inpshape[sdims - 1] : 1;
|
||||
const int Hi = sdims > 1 ? cs->inpshape[sdims] : 1;
|
||||
const int Wi = cs->inpshape[sdims + 1];
|
||||
const int D = sdims > 2 ? cs->outshape[sdims - 1] : 1;
|
||||
const int H = sdims > 1 ? cs->outshape[sdims] : 1;
|
||||
const int W = cs->outshape[sdims + 1];
|
||||
constexpr int MAX_POOL_DIMS = 3; // coordtab/pads/inner use a fixed Z,Y,X frame
|
||||
const int Di = insize[0], Hi = insize[1], Wi = insize[2];
|
||||
const int D = outsize[0], H = outsize[1], W = outsize[2];
|
||||
const int64_t iplanesize = (int64_t)Di*Hi*Wi*C0;
|
||||
const int64_t planesize = (int64_t)D*H*W*C0;
|
||||
const int SZ = cs->strides[0], SY = cs->strides[1], SX = cs->strides[2];
|
||||
const int padZ0 = cs->pads[0], padY0 = cs->pads[1], padX0 = cs->pads[2];
|
||||
const int inner_z0 = cs->inner[0], inner_z1 = cs->inner[MAX_POOL_DIMS];
|
||||
const int inner_y0 = cs->inner[1], inner_y1 = cs->inner[MAX_POOL_DIMS + 1];
|
||||
const int inner_x0 = cs->inner[2], inner_x1 = cs->inner[MAX_POOL_DIMS + 2];
|
||||
const int ksize = (int)cs->ofstab.size();
|
||||
const int* zyxtab = cs->coordtab.data();
|
||||
const int* ofstab = cs->ofstab.data();
|
||||
const int SZ = strides[0], SY = strides[1], SX = strides[2];
|
||||
const int padZ0 = pads[0], padY0 = pads[1], padX0 = pads[2];
|
||||
const int inner_z0 = inner[0], inner_z1 = inner[MAX_POOL_DIMS];
|
||||
const int inner_y0 = inner[1], inner_y1 = inner[MAX_POOL_DIMS + 1];
|
||||
const int inner_x0 = inner[2], inner_x1 = inner[MAX_POOL_DIMS + 2];
|
||||
const int* zyxtab = coordtab;
|
||||
|
||||
for (int nc = task_start; nc < task_end; nc++) {
|
||||
const float* inp = inp_data + nc * iplanesize;
|
||||
@@ -159,35 +148,25 @@ int maxpool32f(const float* inp_data, float* out_data,
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
int avgpool32f(const float* inp_data, float* out_data,
|
||||
const void* state, int count_include_pad,
|
||||
int avgpool32f(const float* inp_data, float* out_data, int C0,
|
||||
const int* insize, const int* outsize, const int* strides,
|
||||
const int* pads, const int* inner, const int* coordtab,
|
||||
const int* ofstab, int ksize, int count_include_pad,
|
||||
int task_start, int task_end)
|
||||
{
|
||||
const cv::dnn::ConvState* cs = static_cast<const cv::dnn::ConvState*>(state);
|
||||
constexpr int MAX_POOL_DIMS = cv::dnn::ConvState::MAX_CONV_DIMS;
|
||||
if (cs->nspatialdims > MAX_POOL_DIMS)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
const int sdims = cs->nspatialdims;
|
||||
const int C0 = cs->inpshape.back();
|
||||
const int Di = sdims > 2 ? cs->inpshape[sdims - 1] : 1;
|
||||
const int Hi = sdims > 1 ? cs->inpshape[sdims] : 1;
|
||||
const int Wi = cs->inpshape[sdims + 1];
|
||||
const int D = sdims > 2 ? cs->outshape[sdims - 1] : 1;
|
||||
const int H = sdims > 1 ? cs->outshape[sdims] : 1;
|
||||
const int W = cs->outshape[sdims + 1];
|
||||
constexpr int MAX_POOL_DIMS = 3; // coordtab/pads/inner use a fixed Z,Y,X frame
|
||||
const int Di = insize[0], Hi = insize[1], Wi = insize[2];
|
||||
const int D = outsize[0], H = outsize[1], W = outsize[2];
|
||||
const int64_t iplanesize = (int64_t)Di*Hi*Wi*C0;
|
||||
const int64_t planesize = (int64_t)D*H*W*C0;
|
||||
const int SZ = cs->strides[0], SY = cs->strides[1], SX = cs->strides[2];
|
||||
const int padZ0 = cs->pads[0], padY0 = cs->pads[1], padX0 = cs->pads[2];
|
||||
const int padZ1 = cs->pads[MAX_POOL_DIMS], padY1 = cs->pads[MAX_POOL_DIMS + 1],
|
||||
padX1 = cs->pads[MAX_POOL_DIMS + 2];
|
||||
const int inner_z0 = cs->inner[0], inner_z1 = cs->inner[MAX_POOL_DIMS];
|
||||
const int inner_y0 = cs->inner[1], inner_y1 = cs->inner[MAX_POOL_DIMS + 1];
|
||||
const int inner_x0 = cs->inner[2], inner_x1 = cs->inner[MAX_POOL_DIMS + 2];
|
||||
const int ksize = (int)cs->ofstab.size();
|
||||
const int* zyxtab = cs->coordtab.data();
|
||||
const int* ofstab = cs->ofstab.data();
|
||||
const int SZ = strides[0], SY = strides[1], SX = strides[2];
|
||||
const int padZ0 = pads[0], padY0 = pads[1], padX0 = pads[2];
|
||||
const int padZ1 = pads[MAX_POOL_DIMS], padY1 = pads[MAX_POOL_DIMS + 1],
|
||||
padX1 = pads[MAX_POOL_DIMS + 2];
|
||||
const int inner_z0 = inner[0], inner_z1 = inner[MAX_POOL_DIMS];
|
||||
const int inner_y0 = inner[1], inner_y1 = inner[MAX_POOL_DIMS + 1];
|
||||
const int inner_x0 = inner[2], inner_x1 = inner[MAX_POOL_DIMS + 2];
|
||||
const int* zyxtab = coordtab;
|
||||
const float iksize = 1.f/ksize; // interior has no padding: denom == ksize either way
|
||||
|
||||
for (int nc = task_start; nc < task_end; nc++) {
|
||||
|
||||
Reference in New Issue
Block a user