This is an automated email from the ASF dual-hosted git repository.

junrushao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git


The following commit(s) were added to refs/heads/main by this push:
     new bb56f2a972 [MetaSchedule][UX] Convenient Object Creation (#12643)
bb56f2a972 is described below

commit bb56f2a972606b33e5479d1e18d4c4f13751eeed
Author: Junru Shao <[email protected]>
AuthorDate: Fri Sep 2 00:47:38 2022 -0700

    [MetaSchedule][UX] Convenient Object Creation (#12643)
    
    This PR introduces a set of `.create` methods making it easier to create
    MetaSchedule objects.
    
    For example:
    
    ```python
    ms.database.JSONDatabase(...)
    ms.database.create("json")
    
    ms.runner.RPCRunner(...)
    ms.runner.create("rpc")
    ```
    
    Besides, this PR allows `JSONDatabase` to be created via `work_dir`:
    
    ```python
    db = ms.database.create("json", work_dir="/path/to/db/")
    db = ms.database.create(work_dir="/path/to/db/")  # or even simpler
    ```
---
 python/tvm/meta_schedule/builder/__init__.py       |  2 +-
 python/tvm/meta_schedule/builder/builder.py        | 17 +++++++++
 python/tvm/meta_schedule/database/__init__.py      |  2 +-
 python/tvm/meta_schedule/database/database.py      | 41 +++++++++++++++++++++-
 python/tvm/meta_schedule/database/json_database.py | 31 ++++++++++++----
 python/tvm/meta_schedule/runner/__init__.py        | 12 +++++--
 python/tvm/meta_schedule/runner/runner.py          | 22 +++++++++++-
 .../tvm/meta_schedule/search_strategy/__init__.py  |  2 +-
 .../search_strategy/search_strategy.py             | 29 +++++++++++++++
 .../tvm/meta_schedule/space_generator/__init__.py  |  2 +-
 .../space_generator/space_generator.py             | 28 +++++++++++++++
 .../tvm/meta_schedule/task_scheduler/__init__.py   |  4 +--
 .../meta_schedule/task_scheduler/task_scheduler.py | 20 +++++++++++
 python/tvm/meta_schedule/testing/relay_workload.py |  4 +--
 14 files changed, 198 insertions(+), 18 deletions(-)

diff --git a/python/tvm/meta_schedule/builder/__init__.py 
b/python/tvm/meta_schedule/builder/__init__.py
index 859c74d756..ac71e3a0c1 100644
--- a/python/tvm/meta_schedule/builder/__init__.py
+++ b/python/tvm/meta_schedule/builder/__init__.py
@@ -19,5 +19,5 @@ The tvm.meta_schedule.builder package.
 Meta Schedule builders that translate IRModule to runtime.Module,
 and then export
 """
-from .builder import Builder, BuilderInput, BuilderResult, PyBuilder
+from .builder import Builder, BuilderInput, BuilderResult, PyBuilder, create
 from .local_builder import LocalBuilder
diff --git a/python/tvm/meta_schedule/builder/builder.py 
b/python/tvm/meta_schedule/builder/builder.py
index daa9f7be42..a2254f2433 100644
--- a/python/tvm/meta_schedule/builder/builder.py
+++ b/python/tvm/meta_schedule/builder/builder.py
@@ -17,6 +17,10 @@
 """Meta Schedule builders that translate IRModule to runtime.Module, and then 
export"""
 from typing import Callable, Dict, List, Optional
 
+# isort: off
+from typing_extensions import Literal
+
+# isort: on
 from tvm._ffi import register_object
 from tvm.ir import IRModule
 from tvm.runtime import NDArray, Object
@@ -164,3 +168,16 @@ class PyBuilder:
             The results of building the given inputs.
         """
         raise NotImplementedError
+
+
+def create(  # pylint: disable=keyword-arg-before-vararg
+    kind: Literal["local"] = "local",
+    *args,
+    **kwargs,
+) -> Builder:
+    """Create a Builder."""
+    from . import LocalBuilder  # pylint: disable=import-outside-toplevel
+
+    if kind == "local":
+        return LocalBuilder(*args, **kwargs)  # type: ignore
+    raise ValueError(f"Unknown Builder: {kind}")
diff --git a/python/tvm/meta_schedule/database/__init__.py 
b/python/tvm/meta_schedule/database/__init__.py
index 679923e479..66d011ed52 100644
--- a/python/tvm/meta_schedule/database/__init__.py
+++ b/python/tvm/meta_schedule/database/__init__.py
@@ -18,7 +18,7 @@
 The tvm.meta_schedule.database package.
 The database that stores serialized tuning records and workloads
 """
-from .database import Database, PyDatabase, TuningRecord, Workload
+from .database import Database, PyDatabase, TuningRecord, Workload, create
 from .json_database import JSONDatabase
 from .memory_database import MemoryDatabase
 from .ordered_union_database import OrderedUnionDatabase
diff --git a/python/tvm/meta_schedule/database/database.py 
b/python/tvm/meta_schedule/database/database.py
index aa509b7151..7a1338f46b 100644
--- a/python/tvm/meta_schedule/database/database.py
+++ b/python/tvm/meta_schedule/database/database.py
@@ -17,12 +17,16 @@
 """TuningRecord database"""
 from typing import Any, Callable, List, Optional, Union
 
+# isort: off
+from typing_extensions import Literal
+
+# isort: on
+
 from tvm._ffi import register_object
 from tvm.ir.module import IRModule
 from tvm.runtime import Object
 from tvm.target import Target
 from tvm.tir.schedule import Schedule, Trace
-from typing_extensions import Literal  # pylint: disable=wrong-import-order
 
 from .. import _ffi_api
 from ..arg_info import ArgInfo
@@ -483,3 +487,38 @@ class PyDatabase:
             The number of records in the database
         """
         raise NotImplementedError
+
+
+def create(  # pylint: disable=keyword-arg-before-vararg
+    kind: Union[
+        Literal[
+            "json",
+            "memory",
+            "union",
+            "ordered_union",
+        ],
+        Callable[[Schedule], bool],
+    ] = "json",
+    *args,
+    **kwargs,
+) -> Database:
+    """Create a Database."""
+    from . import (  # pylint: disable=import-outside-toplevel
+        JSONDatabase,
+        MemoryDatabase,
+        OrderedUnionDatabase,
+        ScheduleFnDatabase,
+        UnionDatabase,
+    )
+
+    if callable(kind):
+        return ScheduleFnDatabase(kind, *args, **kwargs)  # type: ignore
+    if kind == "json":
+        return JSONDatabase(*args, **kwargs)
+    if kind == "memory":
+        return MemoryDatabase(*args, **kwargs)  # type: ignore
+    if kind == "union":
+        return UnionDatabase(*args, **kwargs)  # type: ignore
+    if kind == "ordered_union":
+        return OrderedUnionDatabase(*args, **kwargs)  # type: ignore
+    raise ValueError(f"Unknown Database: {kind}")
diff --git a/python/tvm/meta_schedule/database/json_database.py 
b/python/tvm/meta_schedule/database/json_database.py
index 6897b82d98..b36ac61ef2 100644
--- a/python/tvm/meta_schedule/database/json_database.py
+++ b/python/tvm/meta_schedule/database/json_database.py
@@ -15,6 +15,9 @@
 # specific language governing permissions and limitations
 # under the License.
 """The default database that uses a JSON File to store tuning records"""
+import os.path as osp
+from typing import Optional
+
 from tvm._ffi import register_object
 
 from .. import _ffi_api
@@ -38,21 +41,37 @@ class JSONDatabase(Database):
 
     def __init__(
         self,
-        path_workload: str,
-        path_tuning_record: str,
+        path_workload: Optional[str] = None,
+        path_tuning_record: Optional[str] = None,
+        *,
+        work_dir: Optional[str] = None,
         allow_missing: bool = True,
     ) -> None:
         """Constructor.
 
         Parameters
         ----------
-        path_workload : str
-            The path to the workload table.
-        path_tuning_record : str
-            The path to the tuning record table.
+        path_workload : Optional[str] = None
+            The path to the workload table. If not specified,
+            will be generated from `work_dir` as 
`$work_dir/database_workload.json`.
+        path_tuning_record : Optional[str] = None
+            The path to the tuning record table. If not specified,
+            will be generated from `work_dir` as 
`$work_dir/database_tuning_record.json`.
+        work_dir : Optional[str] = None
+            The work directory, if specified, will be used to generate 
`path_tuning_record`
+            and `path_workload`.
         allow_missing : bool
             Whether to create new file when the given path is not found.
         """
+        if work_dir is not None:
+            if path_workload is None:
+                path_workload = osp.join(work_dir, "database_workload.json")
+            if path_tuning_record is None:
+                path_tuning_record = osp.join(work_dir, 
"database_tuning_record.json")
+        if path_workload is None:
+            raise ValueError("`path_workload` is not specified.")
+        if path_tuning_record is None:
+            raise ValueError("`path_tuning_record` is not specified.")
         self.__init_handle_by_constructor__(
             _ffi_api.DatabaseJSONDatabase,  # type: ignore # pylint: 
disable=no-member
             path_workload,
diff --git a/python/tvm/meta_schedule/runner/__init__.py 
b/python/tvm/meta_schedule/runner/__init__.py
index 413bea6d2f..f0e1028bbf 100644
--- a/python/tvm/meta_schedule/runner/__init__.py
+++ b/python/tvm/meta_schedule/runner/__init__.py
@@ -19,6 +19,14 @@ The tvm.meta_schedule.runner package.
 Meta Schedule runners that runs an artifact either locally or through the RPC 
interface
 """
 from .config import EvaluatorConfig, RPCConfig
-from .rpc_runner import RPCRunner
 from .local_runner import LocalRunner, LocalRunnerFuture
-from .runner import PyRunner, Runner, RunnerFuture, RunnerInput, RunnerResult, 
PyRunnerFuture
+from .rpc_runner import RPCRunner
+from .runner import (
+    PyRunner,
+    PyRunnerFuture,
+    Runner,
+    RunnerFuture,
+    RunnerInput,
+    RunnerResult,
+    create,
+)
diff --git a/python/tvm/meta_schedule/runner/runner.py 
b/python/tvm/meta_schedule/runner/runner.py
index 90b53fde8c..539e47f15c 100644
--- a/python/tvm/meta_schedule/runner/runner.py
+++ b/python/tvm/meta_schedule/runner/runner.py
@@ -15,7 +15,12 @@
 # specific language governing permissions and limitations
 # under the License.
 """Runners"""
-from typing import Callable, Optional, List
+from typing import Callable, List, Optional
+
+# isort: off
+from typing_extensions import Literal
+
+# isort: on
 
 from tvm._ffi import register_object
 from tvm.runtime import Object
@@ -223,3 +228,18 @@ class PyRunner:
             The runner futures.
         """
         raise NotImplementedError
+
+
+def create(  # pylint: disable=keyword-arg-before-vararg
+    kind: Literal["local", "rpc"] = "local",
+    *args,
+    **kwargs,
+) -> Runner:
+    """Create a Runner."""
+    from . import LocalRunner, RPCRunner  # pylint: 
disable=import-outside-toplevel
+
+    if kind == "local":
+        return LocalRunner(*args, **kwargs)  # type: ignore
+    elif kind == "rpc":
+        return RPCRunner(*args, **kwargs)  # type: ignore
+    raise ValueError(f"Unknown Runner: {kind}")
diff --git a/python/tvm/meta_schedule/search_strategy/__init__.py 
b/python/tvm/meta_schedule/search_strategy/__init__.py
index 2046067d6c..ffe7e14739 100644
--- a/python/tvm/meta_schedule/search_strategy/__init__.py
+++ b/python/tvm/meta_schedule/search_strategy/__init__.py
@@ -23,4 +23,4 @@ to generate measure candidates.
 from .evolutionary_search import EvolutionarySearch
 from .replay_func import ReplayFunc
 from .replay_trace import ReplayTrace
-from .search_strategy import MeasureCandidate, PySearchStrategy, SearchStrategy
+from .search_strategy import MeasureCandidate, PySearchStrategy, 
SearchStrategy, create
diff --git a/python/tvm/meta_schedule/search_strategy/search_strategy.py 
b/python/tvm/meta_schedule/search_strategy/search_strategy.py
index 1cd8a448fe..e88cdf825a 100644
--- a/python/tvm/meta_schedule/search_strategy/search_strategy.py
+++ b/python/tvm/meta_schedule/search_strategy/search_strategy.py
@@ -20,6 +20,10 @@ candidates for measurement.
 """
 from typing import TYPE_CHECKING, Callable, List, Optional
 
+# isort: off
+from typing_extensions import Literal
+
+# isort: on
 from tvm._ffi import register_object
 from tvm.runtime import Object
 from tvm.tir.schedule import Schedule
@@ -245,3 +249,28 @@ class PySearchStrategy:
             The profiling results from the runner.
         """
         raise NotImplementedError
+
+
+def create(  # pylint: disable=keyword-arg-before-vararg
+    kind: Literal[
+        "evolutionary",
+        "replay_trace",
+        "replay_func",
+    ] = "evolutionary",
+    *args,
+    **kwargs,
+) -> SearchStrategy:
+    """Create a search strategy."""
+    from . import (  # pylint: disable=import-outside-toplevel
+        EvolutionarySearch,
+        ReplayFunc,
+        ReplayTrace,
+    )
+
+    if kind == "evolutionary":
+        return EvolutionarySearch(*args, **kwargs)
+    if kind == "replay_trace":
+        return ReplayTrace(*args, **kwargs)
+    if kind == "replay_func":
+        return ReplayFunc(*args, **kwargs)
+    raise ValueError(f"Unknown SearchStrategy: {kind}")
diff --git a/python/tvm/meta_schedule/space_generator/__init__.py 
b/python/tvm/meta_schedule/space_generator/__init__.py
index d2039c4511..c417ec2d7d 100644
--- a/python/tvm/meta_schedule/space_generator/__init__.py
+++ b/python/tvm/meta_schedule/space_generator/__init__.py
@@ -21,5 +21,5 @@ space for generation of measure candidates.
 """
 from .post_order_apply import PostOrderApply
 from .schedule_fn import ScheduleFn
-from .space_generator import PySpaceGenerator, ScheduleFnType, SpaceGenerator
+from .space_generator import PySpaceGenerator, ScheduleFnType, SpaceGenerator, 
create
 from .space_generator_union import SpaceGeneratorUnion
diff --git a/python/tvm/meta_schedule/space_generator/space_generator.py 
b/python/tvm/meta_schedule/space_generator/space_generator.py
index 74c29b4de0..9d7ebf3bae 100644
--- a/python/tvm/meta_schedule/space_generator/space_generator.py
+++ b/python/tvm/meta_schedule/space_generator/space_generator.py
@@ -20,6 +20,10 @@ space for generation of measure candidates.
 """
 from typing import TYPE_CHECKING, Callable, List, Optional, Union
 
+# isort: off
+from typing_extensions import Literal
+
+# isort: on
 from tvm._ffi import register_object
 from tvm.ir import IRModule
 from tvm.runtime import Object
@@ -132,3 +136,27 @@ class PySpaceGenerator:
             The generated design spaces, i.e., schedules.
         """
         raise NotImplementedError
+
+
+def create(  # pylint: disable=keyword-arg-before-vararg
+    kind: Union[
+        Literal["post_order_apply", "union"],
+        ScheduleFnType,
+    ] = "post_order_apply",
+    *args,
+    **kwargs,
+) -> SpaceGenerator:
+    """Create a design space generator."""
+    from . import (  # pylint: disable=import-outside-toplevel
+        PostOrderApply,
+        ScheduleFn,
+        SpaceGeneratorUnion,
+    )
+
+    if callable(kind):
+        return ScheduleFn(kind, *args, **kwargs)  # type: ignore
+    if kind == "post_order_apply":
+        return PostOrderApply(*args, **kwargs)
+    if kind == "union":
+        return SpaceGeneratorUnion(*args, **kwargs)
+    raise ValueError(f"Unknown SpaceGenerator: {kind}")
diff --git a/python/tvm/meta_schedule/task_scheduler/__init__.py 
b/python/tvm/meta_schedule/task_scheduler/__init__.py
index 1a67aa6f68..51985570b0 100644
--- a/python/tvm/meta_schedule/task_scheduler/__init__.py
+++ b/python/tvm/meta_schedule/task_scheduler/__init__.py
@@ -20,6 +20,6 @@ Meta Schedule task scheduler that manage the task scheduling
 for measure candidates generation and measurement, then save
 records to the database.
 """
-from .task_scheduler import TaskScheduler, PyTaskScheduler
-from .round_robin import RoundRobin
 from .gradient_based import GradientBased
+from .round_robin import RoundRobin
+from .task_scheduler import PyTaskScheduler, TaskScheduler, create
diff --git a/python/tvm/meta_schedule/task_scheduler/task_scheduler.py 
b/python/tvm/meta_schedule/task_scheduler/task_scheduler.py
index 3d57a6b01b..29a5f18dfb 100644
--- a/python/tvm/meta_schedule/task_scheduler/task_scheduler.py
+++ b/python/tvm/meta_schedule/task_scheduler/task_scheduler.py
@@ -19,6 +19,11 @@
 import logging
 from typing import Callable, List, Optional
 
+# isort: off
+from typing_extensions import Literal
+
+# isort: on
+
 from tvm._ffi import register_object
 from tvm.runtime import Object
 
@@ -255,3 +260,18 @@ class PyTaskScheduler:
         """
         # Using self._outer to replace the self pointer
         _ffi_api.TaskSchedulerTouchTask(self._outer(), task_id)  # type: 
ignore # pylint: disable=no-member
+
+
+def create(  # pylint: disable=keyword-arg-before-vararg
+    kind: Literal["round-robin", "gradient"] = "gradient",
+    *args,
+    **kwargs,
+) -> "TaskScheduler":
+    """Create a task scheduler."""
+    from . import GradientBased, RoundRobin  # pylint: 
disable=import-outside-toplevel
+
+    if kind == "round-robin":
+        return RoundRobin(*args, **kwargs)
+    if kind == "gradient":
+        return GradientBased(*args, **kwargs)
+    raise ValueError(f"Unknown TaskScheduler name: {kind}")
diff --git a/python/tvm/meta_schedule/testing/relay_workload.py 
b/python/tvm/meta_schedule/testing/relay_workload.py
index 0162634895..f4f6336df3 100644
--- a/python/tvm/meta_schedule/testing/relay_workload.py
+++ b/python/tvm/meta_schedule/testing/relay_workload.py
@@ -85,7 +85,7 @@ def _get_network(
                 "float32": torch.float32,  # pylint: disable=no-member
             }[dtype]
         )
-        scripted_model = torch.jit.trace(model, input_data).eval()
+        scripted_model = torch.jit.trace(model, input_data).eval()  # type: 
ignore
         input_name = "input0"
         shape_list = [(input_name, input_shape)]
         mod, params = relay.frontend.from_pytorch(scripted_model, shape_list)
@@ -149,7 +149,7 @@ def _get_network(
         input_dtype = "int64"
         a = torch.randint(10000, input_shape)  # pylint: disable=no-member
         model.eval()
-        scripted_model = torch.jit.trace(model, [a], strict=False)
+        scripted_model = torch.jit.trace(model, [a], strict=False)  # type: 
ignore
         input_name = "input_ids"
         shape_list = [(input_name, input_shape)]
         mod, params = relay.frontend.from_pytorch(scripted_model, shape_list)

Reply via email to