Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

zihaomu
Copy link
Member

@zihaomu zihaomu commented Feb 12, 2022

The following Reduce layers of ONNX are supported:

  • ReduceL1
  • ReduceL2
  • ReduceLogSum
  • ReduceLogSumExp
  • ReduceMin
  • ReduceProd
  • ReduceSumSquare

The ReduceSum takes the axes as an input, instead of an attribute, more details, so it is not supported yet.
I remove some cases in dnn/test/test_onnx_conformance_layer_parser_denylist.inl.hpp as unit tests.

Related Issue

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
  • The PR is proposed to the proper branch
  • There is a reference to the original bug report and related work
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
  • The feature is well documented and sample code can be built with the project CMake

Copy link
Contributor

@sl-sergei sl-sergei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you! 👍

Copy link
Member

@rogday rogday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, we have to assert the kernel_size to be 1 in the constructor, if the such "pooling" doesn't actually makes sense with any other kernel size, e.g. everything you added except for min, I think. Also, could you please fix code formatting issues? E.g. add/remove spaces where necessary(in ternary operators, after if and such). Another issue is naming: max_val = min(max, val) looks odd and can be misleading.

@zihaomu
Copy link
Member Author

zihaomu commented Feb 16, 2022

I think, we have to assert the kernel_size to be 1 in the constructor, if such "pooling" doesn't actually make sense with any other kernel size, e.g. everything you added except for min, I think.

Thanks for code reviewing. I don't quite understand why it is necessary to add the assert the kernel_size to be 1. Can you describe it more clearly?

@zihaomu zihaomu force-pushed the add_reduceLayer branch 2 times, most recently from 26c4325 to 3ef4302 Compare February 16, 2022 15:14
Copy link
Member

@rogday rogday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good with a few code style issues.

Copy link
Member

@rogday rogday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 👍

Copy link
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, Huge functions are not really maintainable. Consider avoiding extending them.

Comment on lines 1261 to 1268
for (int d = dstart; d < dend; ++d) {
for (int y = ystart; y < yend; ++y) {
for (int x = xstart; x < xend; ++x) {
const int index = d * inp_width * inp_height + y * inp_width + x;
float val = srcData[index];

switch (poolingType) {
case AVE: case SUM:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having a switch in triple nested for loops are terrible from performance perspective.

We need dedicated "processing runners" for each type. E.g., using templates with functors.


We should not have performance regressions during implementing features.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alalek, I think, the compiler should be able to optimize it since we're not changing poolingType, but you're right, dedicated runners make more sense.

@vpisarev
Copy link
Contributor

@zihaomu, as we discussed, please, do the following changes:

  1. move reduce* operations implementation into a dedicated reduce_layer.cpp
  2. make the reduction operation a template parameter (this part you have already done) without base class and without virtual methods, because calling virtual methods inside the inner loop is terribly slow. Also, please reduce the amount of template code to the minimum. All the reduction operations share many common parts, e.g. shape inference. So, preferably only the processing loop in forward() should be made templates. In some other, non-critical, parts you may use switch operator.
  3. in order to support minpool, please, duplicate the inner loop in maxpooling implementation. Do not place "if" inside the inner loop.

@zihaomu
Copy link
Member Author

zihaomu commented Feb 28, 2022

@zihaomu, as we discussed, please, do the following changes:

  1. move reduce* operations implementation into a dedicated reduce_layer.cpp
  2. make the reduction operation a template parameter (this part you have already done) without base class and without virtual methods, because calling virtual methods inside the inner loop is terribly slow. Also, please reduce the amount of template code to the minimum. All the reduction operations share many common parts, e.g. shape inference. So, preferably only the processing loop in forward() should be made templates. In some other, non-critical, parts you may use switch operator.
  3. in order to support minpool, please, duplicate the inner loop in maxpooling implementation. Do not place "if" inside the inner loop.

Thanks for the code review, I'm refactoring the code.

@zihaomu zihaomu requested review from alalek and rogday March 3, 2022 07:21
Copy link
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for update! Overall looks good.

bool hasSIMD = false;
ReduceOpBase() {}
virtual ~ReduceOpBase() {};
virtual float apply(const float*, const float*, const float ikarea = 1.0f) = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please drop inheritance from functors: alalek@pr21601_r

(with similar change for int8 implementation)

class ReduceOpMIN : public ReduceOpBase
{
public:
bool hasSIMD = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hasSIMD

Looks like it is unused. Please remove.

{
public:
int type;
std::vector<size_t> deletedDims;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deletedDims

reductionDims? or something else?

Could you please add link to some document, e.g. ONNX specification

class CV_EXPORTS ReduceLayer : public Layer
{
public:
int type;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type

reduce_mode? (to avoid confusion with data type)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your code review, all comments have been fixed.

@zihaomu
Copy link
Member Author

zihaomu commented Mar 8, 2022

Hi @alalek, Can you take a look at why the CI of Win64 OpenCL is failed? Thx.


std::swap(shouldDelete[index], shouldDelete[i]);
std::swap(perm[index], perm[i]);
std::swap(inpShape[index], inpShape[i]);
Copy link
Member

@alalek alalek Mar 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build error from logs:

    37>C:\build\precommit_opencl\4.x\opencv\modules\dnn\src\onnx\onnx_importer.cpp(1218,63): error C2665: 'std::swap': none of the 2 overloads could convert all the argument types [C:\build\precommit_opencl\build\modules\dnn\opencv_dnn.vcxproj]
       C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.27.29110\include\thread(200,13): message : could be 'void std::swap(std::thread &,std::thread &) noexcept' (compiling source file C:\build\precommit_opencl\4.x\opencv\modules\dnn\src\onnx\onnx_importer.cpp) [C:\build\precommit_opencl\build\modules\dnn\opencv_dnn.vcxproj]
       C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.27.29110\include\utility(104,19): message : or       'void std::swap<std::_Vb_reference<std::_Wrap_alloc<std::allocator<std::_Vbase>>>,0>(_Ty &,_Ty &) noexcept(<expr>)' [C:\build\precommit_opencl\build\modules\dnn\opencv_dnn.vcxproj]
                 with
                 [
                     _Ty=std::_Vb_reference<std::_Wrap_alloc<std::allocator<std::_Vbase>>>
                 ] (compiling source file C:\build\precommit_opencl\4.x\opencv\modules\dnn\src\onnx\onnx_importer.cpp)
       C:\build\precommit_opencl\4.x\opencv\modules\dnn\src\onnx\onnx_importer.cpp(1218,63): message : while trying to match the argument list '(std::_Vb_reference<std::_Wrap_alloc<std::allocator<std::_Vbase>>>, std::_Vb_reference<std::_Wrap_alloc<std::allocator<std::_Vbase>>>)' [C:\build\precommit_opencl\build\modules\dnn\opencv_dnn.vcxproj]

Looks like there is no std::swap() for elements of std::vector<bool> - as there are no elements references.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot, I will try to solve it.

public:
ReduceOpBase() {}
virtual ~ReduceOpBase() {};
virtual int8_t apply(const int8_t*, const int8_t*) = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still have virtual stuff.
It should be dropped as we use templates.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the code review, I have removed all virtual stuff in the base class, both layers/reduce_layer.cpp and int8_layers/reduce_layer.cpp.

@zihaomu zihaomu force-pushed the add_reduceLayer branch 2 times, most recently from 4a5b1eb to a895e3e Compare March 11, 2022 02:32
@zihaomu zihaomu requested a review from alalek March 11, 2022 02:37
Copy link
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Comment on lines 52 to 58
class ReduceOpBase
{
public:
ReduceOpBase() {}
~ReduceOpBase() {};
int8_t apply(const int8_t*, const int8_t*) { return 0; };
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we even need base class now?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rogday Thx for code reviewing, I have remove the base class, and refactor the code with struct instead of class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category: dnn (onnx) ONNX suport issues in DNN module category: dnn test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants