tvm-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Zhi <notificati...@github.com>
Subject [dmlc/tvm] [RFC][Relay] Port Relay passes to pass manager (#3146)
Date Wed, 08 May 2019 00:52:58 GMT
# Porting Relay Passes to Pass Manager
As the pass manager framework has been merged, we should start to move passes to the pass
manager. This RFC proposes the plans to move the Relay passes.

## Proposal (take constant folding as an example):
The proposal needs to solve problems from both the backend and the frontend. As this could
be a lot of refactoring work, we will mainly focus on the API changes of the pass functions
first, but leave others (like resolving dependency) as follow-up work.

### C++ Backend
The C++ backend implements the functionality of a certain pass as the `pass_func` for `module_pass`
and `function_pass`, i.e. constant folding in this example. Some passes are passed with a
`Module` to identify global vars and/or help report errors, but others are not.

1. Pass `Module` to every pass, or have a global `Module`? When `Module` is not passed, we
can call `GetModule`, like `FromExpr`. For backward compatibility, we can default it to null.
Therefore, users can still invoke the pass as before. All frontend converters should return
a module as well.
2. Previously, many passes are not aware of PassContext. We probably should pass PassContext
into a pass so that the internal context, e.g. ErrorReporter, can be used by each pass. 
3. How can a pass provide the frontend with the most convenient API so that it could be invoked
easily?

```c++
class ConstantFolder : public ExprMutator {
 private:
  PassContext pass_ctx;
  // Other members are omitted..
};

Expr FoldConstant(const Expr& expr, const PassContext& ctx) {
  return ConstantFolder(CreateInterpreter(...), ctx).Mutate(expr);  
}  
  
TVM_REGISTER_API("relay._ir_pass.FoldConstant")  
.set_body([](TVMArgs args, TVMRetValue *ret) {
	PassContext ctx = args[1];
	if (!ctx.defined()) {
		ctx = PassContext();
	}  
    *ret = FoldConstant(args[0], ctx);  
});
```
### Python frontend

Python frontend performs the following tasks
- Link to a pass function, i.e. `ir_pass.fold_constant`
- Register the pass using flattened pass info, e.g. `opt_level`, `name`, and `required` passes.
- Setup `PassContext` when necessary. Otherwise, the backend will create it.
- Create a module for pass execution if it is not passed. 
- Have an API to invoke pass functions in different manner?
	- The old style invocation, `mypass(mod/expr)`, depending on the type of pass, e.g. `ir_pass.fold_constant(expr)`
	- Through pass manager 
```python
	# Create a module for all passes?
        mod = relay.Module({})
        
	# Method 1, Use decorator:
	@ir_pass.function_pass(opt_level=opt_level, name=pass_name)
	def mypass(expr, ctx):
		class Transform(ExprVisitor):
			def __init__():
			def __call__(expr, ctx):
		return Transform(expr, ctx)
	mypass(mod)
		
	# Method 2, pass registered passes directly:	
        pass_func = ir_pass.fold_constant
        cf = ir_pass.function_pass(pass_func, opt_level=2, name=”FoldConstant”, required=[])
 	cf(mod)	
```

## Next Steps
- One pass may call another pass directly. We should setup the `required` field and resolve
dependencies. After that, this pass should be able to access the returned analysis/optimization
results.
- How to represent a `Pass` using pass info, particularly pass name. To resolve pass dependency,
we may only have the `required` passes. We then need to create theses pass and execute them.


-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/dmlc/tvm/issues/3146
Mime
  • Unnamed multipart/alternative (inline, 7-Bit, 0 bytes)
View raw message