1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 15:23:05 +04:00
Files
opencv/modules/dnn/src/opencl/slice.cl
T
Alexander Alekhin 1c8ee3f957 Merge pull request #17885 from alalek:dnn_ocl_slice_update
DNN: OpenCL/slice update

* dnn(ocl/slice): make slice kernel VTune friendly

- more unique names
- inline code of copy functions

* dnn(ocl/slice): prefer to spawn more work groups

- even in case with 1D copy
- perf improvement up to 2x of kernel time (due to changed configuration 128x1x1 => 128x32x1)

* dnn(ocl/slice): cache kernel exec info
2020-08-03 14:13:34 +00:00

265 lines
7.3 KiB
Common Lisp

// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
// Copyright (C) 2020, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
/*
Specialization constants:
- WSZ: size of OpenCL local group
- DIMS: number of working dimensions
- ELEMSIZE: element size in bytes
- DST_SZ_<i>: dst sizes
- SRC_START_<i>: src index shift (slice .start value)
- SRC_STEP_<i>: src steps (bytes)
- DST_STEP_<i>: dst steps (bytes), derived from DST_SZ_<i> and ELEMSIZE
- BLOCK_DIMS: number of dims for copy block (argmax(count(SRC_STEP_<i> != DST_STEP_<i>) <= 1))
- BLOCK_DIMS_CONTIGUOUS (<= BLOCK_DIMS): SRC_STEP_<i> == DST_STEP_<i> for i in [0, BLOCK_DIMS_CONTIGUOUS)
derived specialization constants:
- BLOCK_SIZE: ELEMSIZE * mul(DST_SZ_<i>) for i in [0, BLOCK_DIMS)
- USE_COPY_1D iff BLOCK_DIMS == BLOCK_DIMS_CONTIGUOUS
- BLOCK_COLS:
* with USE_COPY_1D: BLOCK_SIZE
* w/o USE_COPY_1D: ELEMSIZE * mul(DST_SZ_<i>) for i in [0, BLOCK_DIMS_CONTIGUOUS)
- BLOCK_ROWS:
* with USE_COPY_1D: N/A
* w/o USE_COPY_1D: ELEMSIZE * mul(DST_SZ_<i>) for i in [BLOCK_DIMS_CONTIGUOUS, BLOCK_DIMS)
- BLOCK_SRC_STRIDE:
* with USE_COPY_1D: N/A
* w/o USE_COPY_1D: ELEMSIZE * mul(SRC_STEP_<i>) for i in [0, BLOCK_DIMS_CONTIGUOUS)
Note: SZ, STEP values are in reversed order than OpenCV Mat:
- NCHW SZ: [cols, rows, channels, batch]
- NCHW STEP: [elemsize, cols * elemsize, rows * cols * elemsize, ...] (DIMS+1 value)
*/
/*
local: <WSZ, 1, 1>
global: <WSZ, number_of_copy_blocks, 1>
*/
#define CONCAT_(A, B) A##B
#define CONCAT(A, B) CONCAT_(A, B)
#define BLOCK_COLS_X4 (BLOCK_COLS / 4)
#define BLOCK_COLS_X16 (BLOCK_COLS / 16)
__attribute__((reqd_work_group_size(WSZ, 1, 1)))
__kernel void
CONCAT(slice_, SLICE_KERNEL_SUFFIX)(
__global const uchar* src0,
__global uchar* dst0
)
{
uint block_id = get_global_id(1);
uint dst_offset0 = block_id * BLOCK_SIZE;
uint src_offset0 = 0;
{ // calculate src_offset0
#define CALC_SRC_INDEX(dim) \
{ \
uint plane_sz = CONCAT(DST_STEP_, dim) / BLOCK_SIZE; \
CONCAT(idx_, dim) = block_id / plane_sz; \
block_id = block_id - CONCAT(idx_, dim) * plane_sz; \
}
#define UPDATE_SRC_OFFSET(dim) \
src_offset0 = mad24((uint)(CONCAT(idx_, dim) + CONCAT(SRC_START_, dim)), (uint)CONCAT(SRC_STEP_, dim), (uint)src_offset0);
/*
if (get_global_id(0) == 0 && get_global_id(1) == 0) \
printf("(%d, %d): @%d src_offset0=%d idx_dim=%d block_id=%d\n", \
get_global_id(0), get_global_id(1), \
dim, src_offset0, CONCAT(idx_, dim), block_id \
);
*/
#if DIMS > 5
#error "invalid configuration"
#endif
#if DIMS > 4
uint idx_4 = 0;
#if BLOCK_DIMS <= 4
CALC_SRC_INDEX(4)
#endif
UPDATE_SRC_OFFSET(4)
#endif
#if DIMS > 3
uint idx_3 = 0;
#if BLOCK_DIMS <= 3
CALC_SRC_INDEX(3)
#endif
UPDATE_SRC_OFFSET(3)
#endif
#if DIMS > 2
uint idx_2 = 0;
#if BLOCK_DIMS <= 2
CALC_SRC_INDEX(2)
#endif
UPDATE_SRC_OFFSET(2)
#endif
#if DIMS > 1
uint idx_1 = 0;
#if BLOCK_DIMS <= 1
CALC_SRC_INDEX(1)
#endif
UPDATE_SRC_OFFSET(1)
#endif
#if DIMS > 0
uint idx_0 = 0;
UPDATE_SRC_OFFSET(0)
#endif
/*
if (get_global_id(0) == 0)
printf("(%d, %d): src_offset0=%d dst_offset0=%d\n",
get_global_id(0), get_global_id(1),
src_offset0, dst_offset0
);
*/
} // calculate src_offset0
#ifdef USE_COPY_1D
{ // copy_block_1d
__global const uchar* src = src0 + src_offset0;
__global uchar* dst = dst0 + dst_offset0;
uint processed = 0;
#if BLOCK_COLS_X16 >= 4
{
// uchar16 x 4rows per iteration
uint i = get_local_id(0) * 16; // uchar16
while (i < BLOCK_COLS_X16 * 16)
{
uint4 idx0 = (uint4)i;
uint4 idx = idx0 + (uint4)(0, 16 * WSZ, 32 * WSZ, 48 * WSZ);
idx = select(idx0, idx, idx < (BLOCK_COLS_X16 * 16));
uchar16 a0 = vload16(0, src + idx.s0);
uchar16 a1 = vload16(0, src + idx.s1);
uchar16 a2 = vload16(0, src + idx.s2);
uchar16 a3 = vload16(0, src + idx.s3);
vstore16(a0, 0, dst + idx.s0);
vstore16(a1, 0, dst + idx.s1);
vstore16(a2, 0, dst + idx.s2);
vstore16(a3, 0, dst + idx.s3);
i += WSZ * 16 * 4;
}
processed = BLOCK_COLS_X16 * 16;
}
#else
#define SKIP_1D_BLOCK_COLS_X16 1
#endif
#if BLOCK_COLS_X4 > 0 && (defined(SKIP_1D_BLOCK_COLS_X16) || (BLOCK_COLS_X16 * 16 != BLOCK_COLS_X4 * 4))
{
// uchar4 x 4rows per iteration
uint i = get_local_id(0) * 4 + processed; // uchar4
while (i < BLOCK_COLS_X4 * 4)
{
uint4 idx0 = (uint4)i;
uint4 idx = idx0 + (uint4)(0, 4 * WSZ, 8 * WSZ, 12 * WSZ);
idx = select(idx0, idx, idx < (BLOCK_COLS_X4 * 4));
uchar4 a0 = vload4(0, src + idx.s0);
uchar4 a1 = vload4(0, src + idx.s1);
uchar4 a2 = vload4(0, src + idx.s2);
uchar4 a3 = vload4(0, src + idx.s3);
vstore4(a0, 0, dst + idx.s0);
vstore4(a1, 0, dst + idx.s1);
vstore4(a2, 0, dst + idx.s2);
vstore4(a3, 0, dst + idx.s3);
i += WSZ * 4 * 4;
}
processed = BLOCK_COLS_X4 * 4;
}
#else
#define SKIP_1D_BLOCK_COLS_X4 1
#endif // BLOCK_COLS_X4 > 0
#if (defined(SKIP_1D_BLOCK_COLS_X16) && defined(SKIP_1D_BLOCK_COLS_X4)) || BLOCK_COLS_X4 * 4 != BLOCK_COLS
{
uint i = get_local_id(0) + processed;
while (i < BLOCK_COLS)
{
uchar a0 = src[i];
dst[i] = a0;
i += WSZ;
}
}
#endif
} // copy_block_1d
#else
{ // copy_block_2d
__global const uchar* src = src0 + src_offset0;
__global uchar* dst = dst0 + dst_offset0;
uint i = get_local_id(0) * 4;
#define BLOCK_COLS_FILL_X4 (((BLOCK_COLS + 3) / 4) * 4)
#define BLOCK_SIZE_FILL_X4 (BLOCK_COLS_FILL_X4 * BLOCK_ROWS)
while (i < BLOCK_SIZE_FILL_X4)
{
int row = i / BLOCK_COLS_FILL_X4;
int col = i % BLOCK_COLS_FILL_X4;
uint src_offset = row * BLOCK_SRC_STRIDE + col;
#if BLOCK_COLS_FILL_X4 == BLOCK_COLS
uint dst_offset = i;
#else
uint dst_offset = row * BLOCK_COLS + col;
#endif
#if BLOCK_COLS_FILL_X4 != BLOCK_COLS
if (col <= BLOCK_COLS - 4)
#endif
{
uchar4 a = vload4(0, src + src_offset);
vstore4(a, 0, dst + dst_offset);
}
#if BLOCK_COLS_FILL_X4 != BLOCK_COLS
else
{
/* non-optimized reference code
while (col < BLOCK_COLS)
{
uchar a = src[src_offset];
dst[dst_offset] = a;
col++;
src_offset++;
dst_offset++;
}
*/
uint4 shift = (uint4)(0, 1, 2, 3);
shift = select((uint4)0, shift, col + shift < BLOCK_COLS);
dst[dst_offset + shift.s0] = src[src_offset + shift.s0];
#if BLOCK_COLS_FILL_X4 - BLOCK_COLS <= 2
dst[dst_offset + shift.s1] = src[src_offset + shift.s1];
#endif
#if BLOCK_COLS_FILL_X4 - BLOCK_COLS <= 1
dst[dst_offset + shift.s2] = src[src_offset + shift.s2];
#endif
}
#endif // BLOCK_COLS_FILL_X4 != BLOCK_COLS
i += WSZ * 4;
}
} // copy_block_2d
#endif
}