This is a follow up on top of my previous question on graph partition.
To generate sub graphs from an existing graph(for debugging purpose), I am curious to get some insight on how can fused operators (in graph.json) correlate with relay IR.
The output of relay.build
step gives serialized relay IR.
lib = relay.build(mod, target, target_host=target, params=params)
If I print lib.ir_mod
, it shows relay IR which has serial nodes for the functions in fused functions i.e. if the fused function name is tvmgen_default_fused_nn_conv2d_add_nn_relu
, the relay IR looks like this
%3 = nn.conv2d(%1, %2, padding=[1, 1, 1, 1], channels=64, kernel_size=[3, 3], out_dtype="float16") /* ty=Tensor[(1, 64, 224, 224), float16] */; %4 = cast(%block1_conv1/BiasAdd/ReadVariableOp:0, dtype="float16") /* ty=Tensor[(64), float16] */; %5 = nn.bias_add(%3, %4) /* ty=Tensor[(1, 64, 224, 224), float16] */; %6 = nn.relu(%5) /* ty=Tensor[(1, 64, 224, 224), float16] */;
I have two questions:
- Shouldn’t the output
lib.ir_mod
contain nodes/functions representing fused operators in graph.json instead of unfused operators ? - Is there a way to get a mapping between fused operators(in graph.json) and relay IR(output if relay.build) ? It would be helpful if there is some debug information to help in correlating relay IR with fused operators.
The reason to get correlation : Graph.json can be viewed by end users and the node_row_ptr
in graph.json can be used to mention start and end node of sub graph. If a relation can be established between fused ops and relay IR, we can use compiler_start
and compiler_end
attributes to partition the graph using GraphPartition()
function and compile it for respective hardware.
Requesting for help and thank you in advance!
CC: @comaniac , @csullivan