1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 23:33:05 +04:00

Merge pull request #17363 from YashasSamaga:cuda4dnn-eltwise-fusion2

cuda4dnn(conv): fuse eltwise with convolutions

* fuse eltwise with convolutions

* manually rebase to avoid bad git merge
This commit is contained in:
Yashas Samaga B L
2020-07-09 18:32:21 +05:30
committed by GitHub
parent 44d473fba0
commit d0e6d2438c
22 changed files with 1636 additions and 300 deletions
+54 -2
View File
@@ -248,6 +248,7 @@ public:
#endif
#ifdef HAVE_CUDA
cuda4dnn::ConvolutionConfiguration::FusionMode cudaFusionMode;
cuda4dnn::ConvolutionConfiguration::ActivationType cudaActType;
float cuda_relu_slope, cuda_crelu_floor, cuda_crelu_ceil, cuda_power_exp;
#endif
@@ -261,6 +262,7 @@ public:
#endif
#ifdef HAVE_CUDA
cudaFusionMode = cuda4dnn::ConvolutionConfiguration::FusionMode::NONE;
cudaActType = cuda4dnn::ConvolutionConfiguration::ActivationType::IDENTITY;
#endif
}
@@ -425,10 +427,18 @@ public:
#endif
#ifdef HAVE_CUDA
cudaActType = cuda4dnn::ConvolutionConfiguration::ActivationType::IDENTITY;
if (activ.empty())
{
/* setActivation was called with empty argument => reset all fusions */
cudaFusionMode = cuda4dnn::ConvolutionConfiguration::FusionMode::NONE;
cudaActType = cuda4dnn::ConvolutionConfiguration::ActivationType::IDENTITY;
}
if(IS_DNN_CUDA_TARGET(preferableTarget))
{
CV_Assert(cudaFusionMode == ConvolutionConfiguration::FusionMode::NONE ||
cudaFusionMode == ConvolutionConfiguration::FusionMode::ELTWISE_SUM);
Ptr<ReLULayer> activ_relu = activ.dynamicCast<ReLULayer>();
if(!activ_relu.empty())
{
@@ -475,12 +485,53 @@ public:
cudaActType = cuda4dnn::ConvolutionConfiguration::ActivationType::MISH;
if (cudaActType == cuda4dnn::ConvolutionConfiguration::ActivationType::IDENTITY)
{
/* no activation fused */
activ.reset();
}
else
{
/* activation was fused */
if (cudaFusionMode == ConvolutionConfiguration::FusionMode::NONE) /* no previous fusion */
cudaFusionMode = ConvolutionConfiguration::FusionMode::ACTIVATION; /* now activation */
else if (cudaFusionMode == ConvolutionConfiguration::FusionMode::ELTWISE_SUM) /* previously eltwise was fused */
cudaFusionMode = ConvolutionConfiguration::FusionMode::ELTWISE_SUM_THEN_ACTIVATION; /* now activation on eltwise output */
}
}
#endif
return !activ.empty();
}
virtual bool tryFuse(Ptr<Layer>& top) CV_OVERRIDE
{
#ifdef HAVE_CUDA
if(IS_DNN_CUDA_TARGET(preferableTarget))
{
Ptr<EltwiseLayer> eltwise = top.dynamicCast<EltwiseLayer>();
if (!eltwise.empty()) // && eltwise->op == EltwiseLayer::SUM && eltwise->coeffs.empty())
{
/* we also need to check that the eltwise input does not require shortcut mechanism
* it's difficult to verify it here but we hope that `fuseLayers` has done the check already
*/
if (cudaFusionMode == ConvolutionConfiguration::FusionMode::NONE)
{
/* no previous fusion */
cudaFusionMode = ConvolutionConfiguration::FusionMode::ELTWISE_SUM; /* now eltwise */
return true;
}
else if(cudaFusionMode == ConvolutionConfiguration::FusionMode::ACTIVATION)
{
/* previously an activation was fused */
cudaFusionMode = ConvolutionConfiguration::FusionMode::ACTIVATION_THEN_ELTWISE_SUM;
return true;
}
return false;
}
}
#endif
return BaseConvolutionLayerImpl::tryFuse(top);
}
void fuseWeights(const Mat& w_, const Mat& b_) CV_OVERRIDE
{
// Convolution weights have OIHW data layout. Parameters fusion in case of
@@ -1493,7 +1544,7 @@ public:
{
auto context = reinterpret_cast<csl::CSLContext*>(context_);
CV_Assert(inputs.size() == 1);
CV_Assert(inputs.size() == 1 || inputs.size() == 2);
auto input_wrapper = inputs[0].dynamicCast<CUDABackendWrapper>();
auto input_shape = input_wrapper->getShape();
@@ -1534,6 +1585,7 @@ public:
config.output_shape.assign(std::begin(output_shape), std::end(output_shape));
config.groups = groups;
config.fusion_mode = cudaFusionMode;
config.activation_type = cudaActType;
config.relu_negative_slope = cuda_relu_slope;
config.crelu_floor = cuda_crelu_floor;