From 1dbdcfb5e0542dbe43a468ad31a71a674a13e1fa Mon Sep 17 00:00:00 2001 From: Tianqi Chen Date: Thu, 27 Feb 2020 14:27:37 -0800 Subject: [PATCH] [DOCS] Sphinx -- Introduce alias detection. (#4954) * [DOCS] Sphinx -- Introduce alias detection. Background: some of our namespaces import function from another namespace. For example tvm.te imports most of the operators from tvm.tir. Previously we manually exclude these aliases from the doc. However that means we can not link them by the alias name. This PR adds a sphinx callback plugin to detect such aliases, and create a rubric block on the button of its current docstring `Alias of the original class`. It is done in a way so that we can refer to the generated docs. We also fixed a few docs errors. * Fix most of the issues --- docs/api/python/index.rst | 1 - docs/api/python/relay/op.rst | 39 ++--------- docs/api/python/te.rst | 6 -- docs/api/python/tvm.rst | 76 --------------------- docs/conf.py | 104 ++++++++++++++++++++++------- python/tvm/ir/base.py | 12 ++-- python/tvm/relay/op/transform.py | 13 ++-- python/tvm/relay/op/vision/__init__.py | 2 - python/tvm/relay/op/vision/multibox.py | 1 - python/tvm/relay/op/vision/nms.py | 1 - python/tvm/target/generic_func.py | 2 - tutorials/language/intrin_math.py | 4 +- vta/tutorials/frontend/deploy_detection.py | 2 +- 13 files changed, 99 insertions(+), 164 deletions(-) delete mode 100644 docs/api/python/tvm.rst diff --git a/docs/api/python/index.rst b/docs/api/python/index.rst index 796bba8..f62a4b8 100644 --- a/docs/api/python/index.rst +++ b/docs/api/python/index.rst @@ -21,7 +21,6 @@ Python API .. toctree:: :maxdepth: 2 - tvm runtime ndarray error diff --git a/docs/api/python/relay/op.rst b/docs/api/python/relay/op.rst index 3d8460a..898f103 100644 --- a/docs/api/python/relay/op.rst +++ b/docs/api/python/relay/op.rst @@ -18,38 +18,7 @@ tvm.relay.op ------------ .. automodule:: tvm.relay.op - :members: - -.. autofunction:: tvm.relay.op.Op - -.. autofunction:: tvm.relay.op.OpPattern - -.. autofunction:: tvm.relay.op.get - -.. autofunction:: tvm.relay.op.register - -.. autofunction:: tvm.relay.op.register_schedule - -.. autofunction:: tvm.relay.op.register_pattern - -.. autofunction:: tvm.relay.op.register_compute - -.. autofunction:: tvm.relay.op.register_gradient - -.. autofunction:: tvm.relay.op.register_alter_op_layout - -.. autofunction:: tvm.relay.op.schedule_injective - -.. autofunction:: tvm.relay.op.debug - -.. automodule:: tvm.relay.op.reduce - :members: - -.. automodule:: tvm.relay.op.tensor - :members: - -.. automodule:: tvm.relay.op.transform - :members: - -.. automodule:: tvm.relay.op.nn - :members: + :members: + :imported-members: + :exclude-members: Tuple + :autosummary: diff --git a/docs/api/python/te.rst b/docs/api/python/te.rst index 1f70c4d..363dae6 100644 --- a/docs/api/python/te.rst +++ b/docs/api/python/te.rst @@ -22,10 +22,4 @@ tvm.te .. automodule:: tvm.te :members: :imported-members: - :exclude-members: - any, all, min_value, max_value, trace, - exp, erf, tanh, sigmoid, log, cos, sin, atan, sqrt, rsqrt, floor, ceil, - trunc, abs, round, nearbyint, isnan, power, popcount, fmod, if_then_else, - div, indexdiv, indexmod, truncdiv, truncmod, floordiv, floormod, - comm_reducer, min, max, sum :autosummary: diff --git a/docs/api/python/tvm.rst b/docs/api/python/tvm.rst deleted file mode 100644 index 56f3613..0000000 --- a/docs/api/python/tvm.rst +++ /dev/null @@ -1,76 +0,0 @@ -.. Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - -.. http://www.apache.org/licenses/LICENSE-2.0 - -.. Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - -tvm ---- -The user facing API for computation declaration. - -.. autosummary:: - - tvm.var - tvm.size_var - tvm.const - tvm.convert - tvm.placeholder - tvm.compute - tvm.scan - tvm.extern - tvm.decl_buffer - tvm.reduce_axis - tvm.thread_axis - tvm.comm_reducer - tvm.sum - tvm.div - tvm.indexdiv - tvm.indexmod - tvm.truncdiv - tvm.truncmod - tvm.floordiv - tvm.floormod - tvm.min - tvm.max - tvm.tag_scope - tvm.exp - tvm.intrin - tvm.call_pure_extern - -.. autofunction:: tvm.var -.. autofunction:: tvm.size_var -.. autofunction:: tvm.const -.. autofunction:: tvm.convert -.. autofunction:: tvm.placeholder -.. autofunction:: tvm.compute -.. autofunction:: tvm.scan -.. autofunction:: tvm.extern -.. autofunction:: tvm.decl_buffer -.. autofunction:: tvm.reduce_axis -.. autofunction:: tvm.thread_axis -.. autofunction:: tvm.comm_reducer -.. autofunction:: tvm.sum -.. autofunction:: tvm.div -.. autofunction:: tvm.indexdiv -.. autofunction:: tvm.indexmod -.. autofunction:: tvm.truncdiv -.. autofunction:: tvm.truncmod -.. autofunction:: tvm.floordiv -.. autofunction:: tvm.floormod -.. autofunction:: tvm.min -.. autofunction:: tvm.max -.. autofunction:: tvm.tag_scope -.. autofunction:: tvm.exp -.. autofunction:: tvm.intrin -.. autofunction:: tvm.call_pure_extern diff --git a/docs/conf.py b/docs/conf.py index d882f75..95fd1c3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -30,6 +30,7 @@ # All configuration values have a default; values that are commented out # serve to show the default. import sys +import inspect import os, subprocess import shlex import recommonmark @@ -183,19 +184,6 @@ latex_documents = [ author, 'manual'), ] -# hook for doxygen -def run_doxygen(folder): - """Run the doxygen make command in the designated folder.""" - try: - #retcode = subprocess.call("cd %s; make doc" % folder, shell=True) - retcode = subprocess.call("rm -rf _build/html/doxygen", shell=True) - retcode = subprocess.call("mkdir -p _build/html", shell=True) - retcode = subprocess.call("cp -rf doxygen/html _build/html/doxygen", shell=True) - if retcode < 0: - sys.stderr.write("doxygen terminated by signal %s" % (-retcode)) - except OSError as e: - sys.stderr.write("doxygen execution failed: %s" % e) - intersphinx_mapping = { 'python': ('https://docs.python.org/{.major}'.format(sys.version_info), None), 'numpy': ('https://docs.scipy.org/doc/numpy/', None), @@ -224,18 +212,6 @@ def generate_doxygen_xml(app): """Run the doxygen make commands if we're on the ReadTheDocs server""" run_doxygen('..') -def setup(app): - # Add hook for building doxygen xml when needed - # no c++ API for now - app.connect("builder-inited", generate_doxygen_xml) - app.add_stylesheet('css/tvm_theme.css') - app.add_config_value('recommonmark_config', { - 'url_resolver': lambda url: github_doc_root + url, - 'auto_doc_ref': True - }, True) - app.add_transform(AutoStructify) - - sphinx_gallery_conf = { 'backreferences_dir': 'gen_modules/backreferences', 'doc_module': ('tvm', 'numpy'), @@ -255,3 +231,81 @@ sphinx_gallery_conf = { autodoc_default_options = { 'member-order': 'bysource', } + +# hook for doxygen +def run_doxygen(folder): + """Run the doxygen make command in the designated folder.""" + try: + #retcode = subprocess.call("cd %s; make doc" % folder, shell=True) + retcode = subprocess.call("rm -rf _build/html/doxygen", shell=True) + retcode = subprocess.call("mkdir -p _build/html", shell=True) + retcode = subprocess.call("cp -rf doxygen/html _build/html/doxygen", shell=True) + if retcode < 0: + sys.stderr.write("doxygen terminated by signal %s" % (-retcode)) + except OSError as e: + sys.stderr.write("doxygen execution failed: %s" % e) + +# Maps the original namespace to list of potential modules +# that we can import alias from. +tvm_alias_check_map = { + "tvm.te": ["tvm.tir"], + "tvm.tir": ["tvm.ir", "tvm.runtime"], +} + +def update_alias_docstring(name, obj, lines): + """Update the docstring of alias functions. + + This function checks if the obj is an alias of another documented object + in a different module. + + If it is an alias, then it will append the alias information to the docstring. + + Parameters + ---------- + name : str + The full name of the object in the doc. + + obj : object + The original object. + + lines : list + The docstring lines, need to be modified inplace. + """ + arr = name.rsplit(".", 1) + if len(arr) != 2: + return + target_mod, target_name = arr + + if target_mod not in tvm_alias_check_map: + return + if not hasattr(obj, "__module__"): + return + obj_mod = obj.__module__ + + for amod in tvm_alias_check_map[target_mod]: + if not obj_mod.startswith(amod): + continue + + if hasattr(sys.modules[amod], target_name): + obj_type = ":py:func" if callable(obj) else ":py:class" + lines.append( + ".. rubric:: Alias of %s:`%s.%s`" % (obj_type, amod, target_name)) + + +def process_docstring(app, what, name, obj, options, lines): + """Sphinx callback to process docstring""" + if callable(obj) or inspect.isclass(obj): + update_alias_docstring(name, obj, lines) + + +def setup(app): + # Add hook for building doxygen xml when needed + # no c++ API for now + app.connect("builder-inited", generate_doxygen_xml) + app.connect('autodoc-process-docstring', process_docstring) + app.add_stylesheet('css/tvm_theme.css') + app.add_config_value('recommonmark_config', { + 'url_resolver': lambda url: github_doc_root + url, + 'auto_doc_ref': True + }, True) + app.add_transform(AutoStructify) diff --git a/python/tvm/ir/base.py b/python/tvm/ir/base.py index 661a64a..944daa1 100644 --- a/python/tvm/ir/base.py +++ b/python/tvm/ir/base.py @@ -39,16 +39,16 @@ class Node(Object): Optionally annotate function to provide additional information in the comment block. - .. note:: - - The meta data section is necessary to fully parse the text format. - However, it can contain dumps that are big (e.g constant weights), - so it can be helpful to skip printing the meta data section. - Returns ------- text : str The text format of the expression. + + Notes + ----- + The meta data section is necessary to fully parse the text format. + However, it can contain dumps that are big (e.g constant weights), + so it can be helpful to skip printing the meta data section. """ return _ffi_api.AsText(self, show_meta_data, annotate) diff --git a/python/tvm/relay/op/transform.py b/python/tvm/relay/op/transform.py index 15c48df..0955978 100644 --- a/python/tvm/relay/op/transform.py +++ b/python/tvm/relay/op/transform.py @@ -419,12 +419,6 @@ def tile(data, reps): reps : tuple of int The number of times repeating the tensor data. - .. note:: - Each dim size of reps must be a positive integer. If reps has length d, - the result will have dimension of max(d, data.ndim); If data.ndim < d, - data is promoted to be d-dimensional by prepending new axes. - If data.ndim >= d, reps is promoted to a.ndim by pre-pending 1's to it. - Returns ------- ret : relay.Expr @@ -442,6 +436,13 @@ def tile(data, reps): relay.tile(x, reps=(2,)) = [[1., 2., 1., 2.], [3., 4., 3., 4.]] + + Notes + ----- + Each dim size of reps must be a positive integer. If reps has length d, + the result will have dimension of max(d, data.ndim); If data.ndim < d, + data is promoted to be d-dimensional by prepending new axes. + If data.ndim >= d, reps is promoted to a.ndim by pre-pending 1's to it. """ return _make.tile(data, reps) diff --git a/python/tvm/relay/op/vision/__init__.py b/python/tvm/relay/op/vision/__init__.py index da06ca6..55e6bf9 100644 --- a/python/tvm/relay/op/vision/__init__.py +++ b/python/tvm/relay/op/vision/__init__.py @@ -16,8 +16,6 @@ # under the License. # pylint: disable=wildcard-import """Vision network related operators.""" -from __future__ import absolute_import as _abs - from .multibox import * from .nms import * from .rcnn import * diff --git a/python/tvm/relay/op/vision/multibox.py b/python/tvm/relay/op/vision/multibox.py index 065a3e7..55fb01c 100644 --- a/python/tvm/relay/op/vision/multibox.py +++ b/python/tvm/relay/op/vision/multibox.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. """Multibox operations.""" -from __future__ import absolute_import as _abs from . import _make from ...expr import TupleWrapper diff --git a/python/tvm/relay/op/vision/nms.py b/python/tvm/relay/op/vision/nms.py index d19dde3..cba08bf 100644 --- a/python/tvm/relay/op/vision/nms.py +++ b/python/tvm/relay/op/vision/nms.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. """Non-maximum suppression operations.""" -from __future__ import absolute_import as _abs from . import _make from ...expr import TupleWrapper diff --git a/python/tvm/target/generic_func.py b/python/tvm/target/generic_func.py index bfcd2dd..1936ff1 100644 --- a/python/tvm/target/generic_func.py +++ b/python/tvm/target/generic_func.py @@ -116,7 +116,6 @@ def override_native_generic_func(func_name): .. code-block:: python import tvm -from tvm import te # wrap function as target generic @tvm.target.override_native_generic_func("my_func") def my_func(a): @@ -211,7 +210,6 @@ def generic_func(fdefault): .. code-block:: python import tvm -from tvm import te # wrap function as target generic @tvm.target.generic_func def my_func(a): diff --git a/tutorials/language/intrin_math.py b/tutorials/language/intrin_math.py index eebab3f..146263d 100644 --- a/tutorials/language/intrin_math.py +++ b/tutorials/language/intrin_math.py @@ -66,7 +66,7 @@ print(f.imported_modules[0].get_source()) # TVM intrinsic provides the user a mechanism to achieve this, and this # is the recommended way to solve the problem. # The following code use te.exp instead, which create an intrinsic call -# :any:`te.exp` to do the exponential. +# :py::func:`tvm.te.exp` to do the exponential. # n = te.var("n") A = te.placeholder((n,), name='A') @@ -88,7 +88,7 @@ print(fopencl.imported_modules[0].get_source()) ###################################################################### # Intrinsic Lowering Rule # ----------------------- -# When :any:`te.exp` is called, TVM creates an intrinsic Call Expr. +# When :py:func:`tvm.te.exp` is called, TVM creates an intrinsic Call Expr. # TVM uses transformation rules to transform the intrinsic # call to device specific extern calls. # diff --git a/vta/tutorials/frontend/deploy_detection.py b/vta/tutorials/frontend/deploy_detection.py index 09d8465..0d1dbdd 100644 --- a/vta/tutorials/frontend/deploy_detection.py +++ b/vta/tutorials/frontend/deploy_detection.py @@ -16,7 +16,7 @@ # under the License. """ Deploy Pretrained Vision Detection Model from Darknet on VTA -================================================ +============================================================ **Author**: `Hua Jiang `_ This tutorial provides an end-to-end demo, on how to run Darknet YoloV3-tiny -- 2.7.4