This repository has been archived by the owner on May 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 58
[DISCUSS] Relax control flow support #93
Comments
thanks for the great proposal! A few questions:
|
@hypercubestart sorry for my late response, forgot to check the notification. We plan to have a loop operator in the future, it is something like PyTorch prim::loop or tensorflow while_loop. And we will still have recursion since it is more friendly to automatic differentiation. AFAIK, we don't have a very clear idea about whether relying on relay for model conversion or not. Personally, for a long term goal, I think relax needs its own converter converting models directly from original inputs instead of the conversion path model->relay->relax. Relax VM takes similar approaches for primitives as Relay VM. The main differences between relay vm and relax vm are:
|
Merged
YuchenJin
changed the title
[DISCUSSION] Relax control flow support
[DISCUSS] Relax control flow support
Mar 23, 2022
Merged
MasterJH5574
pushed a commit
to MasterJH5574/tlc-relax
that referenced
this issue
Jan 13, 2023
MasterJH5574
pushed a commit
to MasterJH5574/tlc-relax
that referenced
this issue
Jan 13, 2023
MasterJH5574
pushed a commit
to MasterJH5574/tlc-relax
that referenced
this issue
Jan 16, 2023
vinx13
pushed a commit
to vinx13/relax
that referenced
this issue
Jan 31, 2023
vinx13
pushed a commit
to vinx13/relax
that referenced
this issue
Jan 31, 2023
vinx13
pushed a commit
to vinx13/relax
that referenced
this issue
Feb 8, 2023
MasterJH5574
pushed a commit
to MasterJH5574/tlc-relax
that referenced
this issue
Feb 12, 2023
vinx13
pushed a commit
to vinx13/relax
that referenced
this issue
Feb 13, 2023
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Author: @YuchenJin, @yongwww
Introduction
We observe that more and more dynamic models are created with control flow, especially in the fields of object detection and natural language processing. We plan to enable control flow support on Relax to meet the increasing needs. This design document outlines the plan and key steps to support models with control flow (e.g., LSTM, Mask-RCNN) on Relax.
When importing models like SSD, LSTM from PyTorch or TensorFlow to Relay, there are
while_loop
constructs andTensorArray
in the converted relay IR. Thewhile_loop
in Relay is implemented with tail recursion, which needs closure and lambda lifting.TensorArray
is expressed via Relay ADT. In Relax, we can flexibly enable opaque Object type and write opaque packed functions to operate onTensorArray
, more details about TensorArray support on Relax please take a look at discussion #87. The following is part of the relay IR converted from PyTorch LSTM model.Key goals:
If-then-else
Currently, Relax is able to support if-then-else statement. If the condition is true, the true branch is executed, otherwise the execution jumps into the false branch.
We introduced two VM instructions:
If
, andGoto
. When we visitIfNode
in codegen, the relatedIf
andGoto
instructions will be emitted with the calculated offsets.Closure
A closure is a function that remembers its environment (captured variables). For example, we have such a program:
After lambda lifting, f2 becomes a global function f2’:
In this design, we came up with three options to support closure in the Relax VM:
VMClosureObj
in the Relay VM;PackedFunc
is tvm.runtime.Object, so a closure can be stored in a Relax VM register.The challenge of O2 is in order for a closure to function like a standalone PackedFunc, the closure will need to capture the VM itself, and VM also references closure because closure is stored in a vm register. This causes a cyclic reference problem as the lifetime of VM and closure depend on each other. As a result, the ref counts of both VM and closure will never go 0, hence they will never be destructed and end up with memory leak.
In O1, VMClosure does not have a reference to the VM itself and always requires the VM to be available, so there is no cyclic reference issue, so we plan to start with O1, while we can migrate to O3 if there are needs in the future.
Lamda Lifting
The Lambda Lifting will be implemented as a
LambdaLift
pass, which is similar to Relay. The main difference is that we will introduce amake_closure
intrinsic. Whereas in relay, an attributeClosure=1
is used in the function to help tell codegen it is a closure.Recursive function:
Before lambda lifting:
After lambda lifting:
Mutual recursive function calls(functions call into each other):
(leave for future support when we have use cases)
Before lambda lifting:
How to lift: compute the maximum closure of functions that calls into each other(in this case f1 and f2), and lift them together. Importantly, the environment of the closure(f1, f2) should be the union of the variables captured by both functions, so after lambda lifting:
After lambda lifting:
Loop through recursion
We use recursive function to construct loop, loop as an operation is in the future plan. Each time when a model with loop is fed into relax, the frontend converter will construct the recursive function. See the following sample for an example of conversion.
The text was updated successfully, but these errors were encountered: