For graphs with multi branches, there might be more than one execution order. For example, the following DAG can be either executed in d -> e -> f -> out
or e -> d -> f -> out
. However, it seems in relay IR, we cannot determine which order to display when serializing.
a = relay.var("a", shape=[1, 10])
b = relay.var("b", shape=[1, 10])
c = relay.var("c", shape=[1, 10])
d = a + b
e = a * c
f = b / e
out = d - f
fn = relay.Function([a,b,c], out)
print(fn)
'''
fn (%a: Tensor[(1, 10), float32], %b: Tensor[(1, 10), float32], %c: Tensor[(1, 10), float32]) {
%0 = add(%a, %b) /* string */;
%1 = multiply(%a, %c) /* string */;
%2 = divide(%b, %1) /* string */;
subtract(%0, %2) /* string */
}
'''
#wanted version
'''
fn (%a: Tensor[(1, 10), float32], %b: Tensor[(1, 10), float32], %c: Tensor[(1, 10), float32]) {
%1 = multiply(%a, %c) /* string */;
%0 = add(%a, %b) /* string */;
%2 = divide(%b, %1) /* string */;
subtract(%0, %2) /* string */
}
'''
Even we manually switch the order, it will still display the original one
code = '''
fn (%a: Tensor[(1, 10), float32], %b: Tensor[(1, 10), float32], %c: Tensor[(1, 10), float32]) {
%0 = add(%a, %b) /* string */;
%1 = multiply(%a, %c) /* string */;
%2 = divide(%b, %1) /* string */;
subtract(%0, %2) /* string */
}
'''
fn = tvm.parser.parse_expr(code)
print(fn)
'''
fn (%a: Tensor[(1, 10), float32], %b: Tensor[(1, 10), float32], %c: Tensor[(1, 10), float32]) {
%0 = multiply(%a, %c);
%1 = add(%a, %b);
%2 = divide(%b, %0);
subtract(%1, %2)
}
'''