Modifying a Graph Using the Graph Modification API
Graph modification aims to optimize the graph structure through techniques such as replacing some specific subgraphs with a fused operator, which can streamline the compute process, minimize accesses to external memory, and speed up scheduling. You can also directly alter the graph structure, such as, adding an operator between some operators, as needed.
Overview
The following figure shows how to modify a graph by adding operator C between operators A and B. The API call sequence is as follows.

Besides using graph modification APIs, this document describes how to modify a graph by encapsulating graph modification functions into a custom pass. For details, see Implementing Pass Based on the Graph Modification API.
Example
- Include the header files.
1 2 3 4
#include "graph.h" #include "ascend_string.h" #include "ge_ir_build.h" #include "gnode.h"
- (Optional) Before graph modification, call aclgrphDumpGraph to dump the graph to the local directory and view the graph information.
Note that aclgrphDumpGraph is called after the SetInputs and SetOutputs calls. See the following example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
string op_name = "tc_ge_openpass_0001"; // Create a graph object. Graph graph(op_name); // Create a Data operator instance. auto data = op::Data("data").set_attr_index(0); // Define the description of the data tensor. TensorDesc data_desc2(ge::Shape({3, 3, 3, 3}), FORMAT_NHWC, DT_FLOAT); data.update_input_desc_x(data_desc2); data.update_output_desc_y(data_desc2); // Create a MatrixInverse operator instance and set its input to the output of the Data operator. auto matrixinverse = op::MatrixInverse("MatrixInverse").set_input_x(data); // Create a Square operator instance and set its input to the output of the MatrixInverse operator. auto square1 = op::Square("square1").set_input_x(matrixinverse); std::vector<Operator> inputs{data}; std::vector<Operator> outputs{data,square1}; // Call APIs to set the input and output operators of the graph. graph.SetInputs(inputs).SetOutputs(outputs); std::map<std::string, std::string> init_options = { {ge::ir_option::SOC_VERSION,"xxx"} }; // Initialize the model and allocate resources. auto ret = aclgrphBuildInitialize(init_options); EXPECT_EQ(ret, GRAPH_SUCCESS); std::cout << "BuildInitialize before infershape Success." << std::endl; size_t filesize =24; const char* file = "tc_ge_openpass_0001_dump"; // Dump the input graph to a text file. ret = ge::aclgrphDumpGraph(graph,file,filesize); if(ret != GRAPH_SUCCESS) { std::cout<<"dump graph failed."<<std::endl; } // Build an offline model and saves it to the memory buffer. ret = aclgrphBuildModel(graph,op_name); if(ret != GRAPH_SUCCESS) { std::cout<<"aclgrphBuildModel failed."<<std::endl; }
- Insert operator C between operators A and B. The following example inserts operator Abs between operators Const and Add.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
GNode src_node; GNode dst_node; std::vector<GNode> nodes = graph.GetAllNodes(); for(auto &node : nodes) { ge::AscendString name; node.GetName(name); std::string node_name(name.GetString()); if(node_name == CONST) { src_node = node;} else if(node_name == ADD) { dst_node = node;} } graph.RemoveEdge(src_node, 0, dst_node, 0); auto abs = op::Abs("input3_abs"); GNode node_abs = graph.AddNodeByOp(abs); TensorDesc output_tensor_desc; src_node.GetOutputDesc(0, output_tensor_desc); abs.UpdateInputDesc(0, output_tensor_desc); abs.UpdateOutputDesc(0, output_tensor_desc); graph.AddDataEdge(src_node, 0, node_abs, 0); graph.AddDataEdge(node_abs, 0, dst_node, 0);
- Call GetAllNodes to locate the operators Const and Add.
- Call RemoveEdge to remove the edges (data edge or control edge) between operators Const and Add.
- Create an Abs operator object of class Operator by referring to Defining an Operator Using APIs Derived from Operator Prototypes. Alternatively, call OperatorFactory::CreateOperator to create an operator.
- Call AddNodeByOp to create an Abs operator object of class GNode.
After the operator is created, update the input TensorDesc and output TensorDesc based on the output TensorDesc of the source node as required. If TensorDesc is not updated, the default value will be set to infer the tensor shape and type at model build time.
- Call AddDataEdge to add edges between operators Const and Abs and between operators Abs and Add. If control edges already exist, you can call AddControlEdge to add additional control edges as needed.
To insert more than one operator (for example, to insert operators C and D between operators A and B), repeat the preceding steps between operators A and C, operators C and D, and operators D and B.
- Remove operator C between operators A and B. The following example removes operator Abs between operators Const and Add.
1 2
graph.RemoveNode(node_abs); graph.AddDataEdge(src_node, 0, dst_node, 0);
- For details about class GNode, see GNode.