the graph optimizer: conv_relu */
| 637 | |
| 638 | /* the graph optimizer: conv_relu */ |
| 639 | static bool GraphFuseConvReLuCommon(Graph* graph, GraphOptimizer* opt, bool relu6) |
| 640 | { |
| 641 | int node_number = graph->seq_nodes.size(); |
| 642 | std::vector<Subgraph*> orig_sub; |
| 643 | |
| 644 | for(int i = 0; i < node_number; i++) |
| 645 | { |
| 646 | Node* node = graph->seq_nodes[i]; |
| 647 | Operator* op = node->GetOp(); |
| 648 | |
| 649 | if(relu6) |
| 650 | { |
| 651 | if(op->GetName() != "ReLu6") |
| 652 | continue; |
| 653 | } |
| 654 | else |
| 655 | { |
| 656 | if(op->GetName() != "ReLu") |
| 657 | continue; |
| 658 | if(op->GetName() == "ReLu" && dynamic_cast<ReLu*>(op)->GetParam()->negative_slope != 0.f) |
| 659 | { |
| 660 | continue; |
| 661 | } |
| 662 | } |
| 663 | Tensor* input_tensor = node->GetInputTensor(0); |
| 664 | |
| 665 | Node* conv_node = input_tensor->producer->owner; |
| 666 | |
| 667 | op = conv_node->GetOp(); |
| 668 | |
| 669 | if(op->GetName() != "Convolution") |
| 670 | continue; |
| 671 | |
| 672 | // check if node in seq_nodes |
| 673 | |
| 674 | if(!NodeInGraph(conv_node, graph)) |
| 675 | continue; |
| 676 | // if parents has muti_consumer: not fuse |
| 677 | Tensor* conv_otensor = conv_node->GetOutputTensor(0); |
| 678 | if(conv_otensor->consumer.size() > 1) |
| 679 | continue; |
| 680 | Subgraph* sub = new Subgraph("conv_relu"); |
| 681 | |
| 682 | sub->seq_nodes.push_back(conv_node); |
| 683 | sub->seq_nodes.push_back(node); |
| 684 | |
| 685 | sub->input_nodes.push_back(conv_node); |
| 686 | sub->output_nodes.push_back(node); |
| 687 | |
| 688 | /* add const node into seq nodes, |
| 689 | so that they will be removed from origin graph too */ |
| 690 | |
| 691 | for(unsigned int i = 1; i < conv_node->GetInputNum(); i++) |
| 692 | { |
| 693 | Tensor* tensor = conv_node->GetInputTensor(i); |
| 694 | sub->seq_nodes.push_back(tensor->producer->owner); |
| 695 | } |
| 696 |
no test coverage detected