You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by GitBox <gi...@apache.org> on 2022/07/28 20:09:21 UTC

[GitHub] [tvm-rfcs] junrushao1994 commented on pull request #79: [RFC] TVMScript Metaprogramming

junrushao1994 commented on PR #79:
URL: https://github.com/apache/tvm-rfcs/pull/79#issuecomment-1198582332

   To follow up with our latest discussion with @tkonolige @areusch @csullivan @jwfromm et al.
   
   The following questions are raised in our discussion:
   1. Move discussion of vendor IR to tradeoffs / benefits section rather than core motivation.
   2. (Section 2) Parser registration example is a little confusing (dispatch.register), probably just needs more detail, less …
   3. (Section 1) Add tradeoffs section noting that this isnt a typical parser, gives much more pythonic interface, easier testing, more flexibility. 
   4. (Section 3) More discussion around what lives in host language. Maybe need script.host_var and script.quote in part of future work, might be worth highlighting in a future work section.
   5. (Section 2) tradeoff on registration approach.
   
   Our response:
   
   ### 1. Tradeoffs: TVMScript parser is not a typical parser
   
   Unlike a typical parser that converts a token stream to an AST, which in our case, converts python source code to TIR AST, the TVMScript parser is technically speaking a transpiler that transforms a Python AST to TIR AST instead of parsing raw python.
   
   Pros:
   
   1. Python’s AST package provides accurate parsing functionality, so that all issues around ambiguity, grammar and parser performance is a non-issue.
   2. Compared with the existing monolithic TVMScript parser which is 1.5k lines of code, the transpiler provides much easier testing, more pythonic interface and more flexibility. 
   
   Cons:
   
   1. This means we are depending on Python’s AST package - which could come with breaking changes across python versions
   
   ### 2. Registration Logic
   
   The registration logic is in fact quite straightforward. For example, to support TIR’s for-loop syntax like:
   
   ```python
   for i, *many_j, k in T.grid(...): # or anything like T.serial/parallel/vectorized/unroll/thread_binding
     ...
   ```
   
   The registration logic is as simple as calling into our IR-builder:
   
   ```python
   @dispatch.register(token="tir", type_name="For")
   def visit_for(self: Parser, node: doc.For) -> None:
       for_frame = self.eval_expr(node.iter)
       if not isinstance(for_frame, T.ForFrame):
           self.report_error(
               node.iter,
               "Expect the for loop to be one of the following: "
               "range, T.serial, T.grid, T.parallel, T.vectorized, T.unroll, T.thread_binding",
           )
       with self.var_table.with_frame():
           with for_frame as iters:
               self.eval_assign(target=node.target, source=iters, bind_value=bind_value)
               self.visit_body(node.body)
   ```
   
   There is an alternative proposal that registration should happen at class-level instead of method-level, e.g.
   
   ```python
   ## Our RFC
   @dispatch.register(token="tir", type_name="For")
   def registered_method(self: Parser, node: doc.For) -> None: ...
   
   ## Alternative
   @dispatch.register(token="tir"):
   class DispatchOfTIR:
     @staticmethod
     def visit_For(self: Parser, node: doc.For) -> None: ...
   ```
   
   The advantage of the alternative proposal is that it limits the users so that they have to put all the logic inside a class, while the disadvantage is that the class itself doesn’t mean anything other than a collection of static methods, which could bring some confusion if developers attempt to instantiate the class.
   
   To this end, “putting all logic inside a class” is equivalent to “putting all logic inside a file” because the class only serves as a namespace. Therefore, we believe the best design should be as minimal as possible, i.e. without a class.
   
   **Drawback**. Registry is a necessary design when it comes to supporting per-node tooling and multiple IRs at scale. However, less carefully designed registries, for example, relay operator strategy, where definitions span in multiple folders and tens of files, would lead to worse discoverability and debugging experience. On the other hand, in our particular case, because all dispatches for a certain IR is confined in a single file (e.g. [tir.py](http://tir.py/)), it would not be a particular concern.
   
   ### 3. Metaprogramming syntax
   
   A question has been raised on supporting quotations for metaprogramming in languages like MetaOCaml [1].
   
   This feature is very cool, and it could be an important future work for well motivated use-cases. In terms of syntax, we believe the following could be like:
   
   ```python
   with script.quote():   ## <===== hand back control to python interpreter
     arbitrary python program
     with script.unquote():  ## <===== gain control from python interpreter
       parsable TVMScript
   ```
   
   [1] MetaOCaml -- an OCaml dialect for multi-stage programming [https://okmij.org/ftp/ML/MetaOCaml.html](https://okmij.org/ftp/ML/MetaOCaml.html)
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org