mirror of
https://github.com/opencv/opencv.git
synced 2026-09-12 13:23:03 -05:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
@@ -48,6 +48,8 @@
|
||||
#include "layers_common.hpp"
|
||||
#include <opencv2/dnn/shape_utils.hpp>
|
||||
|
||||
#include <opencv2/core/utils/logger.hpp>
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
#include "opencl_kernels_dnn.hpp"
|
||||
#endif
|
||||
@@ -204,58 +206,168 @@ public:
|
||||
finalSliceRanges[i][j] = clamp(finalSliceRanges[i][j], inpShape[j]);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
std::cout << "DEBUG: DNN/Slice: " << outputs.size() << " inpShape=" << inpShape << std::endl;
|
||||
for (int i = 0; i < outputs.size(); ++i)
|
||||
{
|
||||
for (int j = 0; j < finalSliceRanges[i].size(); ++j)
|
||||
{
|
||||
std::cout << finalSliceRanges[i][j];
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
bool forward_ocl(InputArrayOfArrays inputs_, OutputArrayOfArrays outputs_, OutputArrayOfArrays internals_)
|
||||
{
|
||||
#if 1
|
||||
// TODO fix that (brokes YOLOv4-tiny)
|
||||
return false;
|
||||
#else
|
||||
std::vector<UMat> inputs;
|
||||
std::vector<UMat> outputs;
|
||||
|
||||
bool use_half = (inputs_.depth() == CV_16S);
|
||||
inputs_.getUMatVector(inputs);
|
||||
outputs_.getUMatVector(outputs);
|
||||
|
||||
if (inputs[0].dims < 4 || (total(shape(outputs[0]), 0, 2) % 4 != 0) ||
|
||||
(total(shape(outputs[0]), 2) % 4 != 0))
|
||||
return false;
|
||||
CV_Assert(outputs.size() == finalSliceRanges.size());
|
||||
|
||||
String opts;
|
||||
if (use_half)
|
||||
opts = "-DDtype=half -DDtype4=half4 -DDtype8=half8";
|
||||
else
|
||||
opts = "-DDtype=float -DDtype4=float4 -DDtype8=float8";
|
||||
const UMat& inpMat = inputs[0];
|
||||
for (size_t i = 0; i < outputs.size(); i++)
|
||||
const UMat& input = inputs[0];
|
||||
if (input.dims > 5)
|
||||
{
|
||||
int groups = outputs[i].size[0];
|
||||
int channels = outputs[i].size[1];
|
||||
int rows = outputs[i].size[2];
|
||||
int cols = outputs[i].size[3];
|
||||
|
||||
ocl::Kernel kernel("slice", ocl::dnn::slice_oclsrc, opts);
|
||||
size_t local[] = { 128 };
|
||||
size_t global[] = { (size_t)groups * channels / 4 * local[0] };
|
||||
int idx = 0;
|
||||
kernel.set(idx++, ocl::KernelArg::PtrReadOnly(inpMat));
|
||||
kernel.set(idx++, (int)(inpMat.size[2] * inpMat.size[3]));
|
||||
kernel.set(idx++, (int)(rows * cols));
|
||||
kernel.set(idx++, (int)inpMat.size[3]);
|
||||
kernel.set(idx++, (int)cols);
|
||||
kernel.set(idx++, (int)finalSliceRanges[i][2].start);
|
||||
kernel.set(idx++, (int)finalSliceRanges[i][3].start);
|
||||
kernel.set(idx++, ocl::KernelArg::PtrWriteOnly(outputs[i]));
|
||||
bool ret = kernel.run(1, global, local, false);
|
||||
if (!ret)
|
||||
return false;
|
||||
CV_LOG_INFO(NULL, "DNN/OpenCL/Slice: implementation doesn't support dims=" << input.dims << ". Fallback to CPU");
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t WSZ = 128;
|
||||
|
||||
const int dims = input.dims;
|
||||
const int elemSize = (int)input.elemSize();
|
||||
String opts0 = cv::format(
|
||||
"-DDIMS=%d -DELEMSIZE=%d",
|
||||
dims, elemSize
|
||||
);
|
||||
for (int d = 0; d < dims; d++)
|
||||
{
|
||||
opts0 += cv::format(" -DSRC_STEP_%d=%d", d, (int)input.step[dims - 1 - d]);
|
||||
}
|
||||
String kname = cv::format("slice_%d", dims);
|
||||
for (size_t i = 0; i < outputs.size(); i++)
|
||||
{
|
||||
UMat& output = outputs[i];
|
||||
const std::vector<Range>& range = finalSliceRanges[i];
|
||||
|
||||
String opts = opts0;
|
||||
|
||||
CV_CheckEQ(output.dims, dims, "");
|
||||
for (int d = 0; d < dims; d++)
|
||||
{
|
||||
opts += cv::format(" -DDST_STEP_%d=%d -DDST_SZ_%d=%d -DSRC_START_%d=%d",
|
||||
d, (int)output.step[dims - 1 - d],
|
||||
d, (int)output.size[dims - 1 - d],
|
||||
d, (int)range[dims - 1 - d].start
|
||||
);
|
||||
CV_CheckEQ(range[d].size(), (int)output.size[d], "");
|
||||
}
|
||||
|
||||
int block_dims = 0;
|
||||
size_t block_size = elemSize;
|
||||
for (int i = dims - 1; i >= 0; --i)
|
||||
{
|
||||
if (input.step[i] != output.step[i])
|
||||
break;
|
||||
block_size *= output.size[i];
|
||||
block_dims++;
|
||||
}
|
||||
|
||||
const size_t total = output.total() * elemSize;
|
||||
size_t num_blocks = total / block_size;
|
||||
|
||||
if ((num_blocks <= 8 && block_size >= WSZ * 4) || (block_size >= WSZ * 64))
|
||||
{
|
||||
// use 1D copy mode
|
||||
opts += cv::format(" -DUSE_COPY_1D=1");
|
||||
|
||||
opts += cv::format(" -DBLOCK_DIMS=%d", block_dims);
|
||||
opts += cv::format(" -DBLOCK_DIMS_CONTIGUOUS=%d", block_dims);
|
||||
opts += cv::format(" -DBLOCK_SIZE=%d", (int)block_size);
|
||||
|
||||
opts += cv::format(" -DBLOCK_COLS=%d", (int)block_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
// use 2D copy mode
|
||||
int block_cols = block_size;
|
||||
int block_dims_contiguous = block_dims;
|
||||
size_t input_base_step = input.step[dims - 1 - block_dims_contiguous];
|
||||
size_t output_base_step = output.step[dims - 1 - block_dims_contiguous];
|
||||
|
||||
size_t block_rows = 1;
|
||||
for (int i = dims - 1 - block_dims_contiguous; i >= 0; --i)
|
||||
{
|
||||
if (input.step[i] * output_base_step != output.step[i] * input_base_step)
|
||||
break;
|
||||
block_rows *= output.size[i];
|
||||
block_dims++;
|
||||
}
|
||||
|
||||
block_size *= block_rows;
|
||||
|
||||
num_blocks = total / block_size;
|
||||
|
||||
if (block_rows > 1)
|
||||
{
|
||||
opts += cv::format(" -DBLOCK_DIMS=%d", block_dims);
|
||||
opts += cv::format(" -DBLOCK_DIMS_CONTIGUOUS=%d", block_dims_contiguous);
|
||||
opts += cv::format(" -DBLOCK_SIZE=%d", (int)block_size);
|
||||
|
||||
opts += cv::format(" -DBLOCK_COLS=%d", (int)block_cols);
|
||||
|
||||
opts += cv::format(" -DBLOCK_ROWS=%d", (int)block_rows);
|
||||
opts += cv::format(" -DBLOCK_SRC_STRIDE=%d", (int)input_base_step);
|
||||
}
|
||||
else
|
||||
{
|
||||
// use 1D copy mode
|
||||
opts += cv::format(" -DUSE_COPY_1D=1");
|
||||
|
||||
opts += cv::format(" -DBLOCK_DIMS=%d", block_dims_contiguous);
|
||||
opts += cv::format(" -DBLOCK_DIMS_CONTIGUOUS=%d", block_dims_contiguous);
|
||||
opts += cv::format(" -DBLOCK_SIZE=%d", (int)block_size);
|
||||
|
||||
opts += cv::format(" -DBLOCK_COLS=%d", (int)block_size);
|
||||
}
|
||||
}
|
||||
|
||||
const size_t MIN_WORK_ITEMS = 16;
|
||||
if (block_size <= 4 * MIN_WORK_ITEMS)
|
||||
WSZ = 4;
|
||||
else if (block_size <= 8 * MIN_WORK_ITEMS)
|
||||
WSZ = 8;
|
||||
else if (block_size <= 16 * MIN_WORK_ITEMS)
|
||||
WSZ = 16;
|
||||
else if (block_size <= 32 * MIN_WORK_ITEMS)
|
||||
WSZ = 32;
|
||||
else if (block_size <= 64 * MIN_WORK_ITEMS)
|
||||
WSZ = 64;
|
||||
|
||||
opts += cv::format(" -DWSZ=%d", (int)WSZ);
|
||||
|
||||
size_t local[] = { WSZ, 1 };
|
||||
size_t global[] = { WSZ, num_blocks };
|
||||
|
||||
ocl::Kernel kernel(kname.c_str(), ocl::dnn::slice_oclsrc, opts);
|
||||
if (kernel.empty())
|
||||
return false;
|
||||
bool ret = kernel.args(
|
||||
ocl::KernelArg::PtrReadOnly(input),
|
||||
ocl::KernelArg::PtrWriteOnly(output)
|
||||
)
|
||||
.run(2, global, local, false);
|
||||
if (!ret)
|
||||
return false;
|
||||
} // for outputs.size()
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user