| 138 | } |
| 139 | |
| 140 | OptimizationViews NeonBackend::OptimizeSubgraphView(const SubgraphView& subgraph, |
| 141 | const ModelOptions& modelOptions) const |
| 142 | { |
| 143 | OptimizationViews optimizationViews(modelOptions); |
| 144 | |
| 145 | auto it = subgraph.end(); |
| 146 | std::map<LayerGuid, Layer*> untouched; |
| 147 | |
| 148 | while (it != subgraph.begin()) |
| 149 | { |
| 150 | --it; |
| 151 | Layer& base = *(PolymorphicDowncast<Layer*>(*it)); |
| 152 | untouched.insert({base.GetGuid(), &base}); |
| 153 | } |
| 154 | |
| 155 | it = subgraph.end(); |
| 156 | while (it != subgraph.begin()) |
| 157 | { |
| 158 | --it; |
| 159 | Layer& base = *(PolymorphicDowncast<Layer*>(*it)); |
| 160 | |
| 161 | // Fuse activation into previous layer if supported by backend |
| 162 | if ((base.GetType() == LayerType::DepthwiseConvolution2d || base.GetType() == LayerType::Convolution2d |
| 163 | || base.GetType() == LayerType::BatchNormalization || base.GetType() == LayerType::FullyConnected |
| 164 | || base.GetType() == LayerType::Addition || base.GetType() == LayerType::Multiplication |
| 165 | || base.GetType() == LayerType::Subtraction || base.GetType() == LayerType::Division |
| 166 | || base.GetType() == LayerType::ElementwiseBinary) |
| 167 | && (base.GetAdditionalInformation<ActivationDescriptor>() == nullptr)) |
| 168 | { |
| 169 | for (auto output = base.BeginOutputSlots(); output != base.EndOutputSlots(); ++output) |
| 170 | { |
| 171 | if (output->GetNumConnections() == 1) |
| 172 | { |
| 173 | for (auto&& childInput : output->GetConnections()) |
| 174 | { |
| 175 | if ((childInput->GetOwningLayer().GetType() == LayerType::Activation) && |
| 176 | (checkDataTypeInputandOutput(childInput->GetOwningLayer()))) |
| 177 | { |
| 178 | Layer& child = childInput->GetOwningLayer(); |
| 179 | |
| 180 | auto* activationLayer = PolymorphicDowncast<ActivationLayer*>(&child); |
| 181 | // Before we proceed make sure that this activation layer is in the subgraph. It could be |
| 182 | // the first layer in the next subgraph. |
| 183 | if (untouched.find(activationLayer->GetGuid()) == untouched.end()) |
| 184 | { |
| 185 | // We can't fuse a layer that's outside the subgraph. |
| 186 | break; |
| 187 | } |
| 188 | const std::string name = std::string("fused-") + child.GetName() + std::string("-into-") + |
| 189 | base.GetName(); |
| 190 | |
| 191 | // Get params from activation layer |
| 192 | ActivationDescriptor activationDesc = activationLayer->GetParameters(); |
| 193 | |
| 194 | if (base.GetType() == LayerType::Convolution2d) |
| 195 | { |
| 196 | Convolution2dLayer* baseLayer = PolymorphicDowncast<Convolution2dLayer*>(&base); |
| 197 |
nothing calls this directly
no test coverage detected