Files
apache--tvm/python/tvm/s_tir/meta_schedule/tir_integration.py
T
wehub-resource-sync 26446540fa
Lint / lint (push) Has been cancelled
CI / MacOS (push) Has been cancelled
CI / Windows (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:36:25 +08:00

274 lines
9.1 KiB
Python

# 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.
"""MetaSchedule-TIR integration"""
from collections.abc import Mapping
# isort: off
from typing import Literal
from tvm_ffi import register_global_func
# isort: on
from tvm import ir, tirx
from tvm.s_tir.schedule import Schedule as _Schedule
from tvm.target import Target
from tvm.tirx.expr import IntImm
from .builder import Builder
from .cost_model import CostModel
from .database import Database
from .logging import get_loggers_from_work_dir
from .measure_callback import MeasureCallback
from .runner import Runner
from .search_strategy import SearchStrategy
from .space_generator import SpaceGenerator
from .task_scheduler import TaskScheduler
from .tune import tune_tasks
from .tune_context import TuneContext, _normalize_mod
from .utils import fork_seed
def tune_tir( # pylint: disable=too-many-locals
mod: ir.IRModule | tirx.PrimFunc,
target: str | Target,
work_dir: str,
max_trials_global: int,
*,
max_trials_per_task: int | None = None,
num_trials_per_iter: int = 64,
builder: Builder.BuilderType = "local",
runner: Runner.RunnerType = "local",
database: Database.DatabaseType = "json",
cost_model: CostModel.CostModelType = "xgb",
measure_callbacks: MeasureCallback.CallbackListType = "default",
task_scheduler: TaskScheduler.TaskSchedulerType = "gradient",
space: SpaceGenerator.SpaceGeneratorType = "post-order-apply",
strategy: SearchStrategy.SearchStrategyType = "evolutionary",
num_tuning_cores: Literal["physical", "logical"] | int = "physical",
seed: int | None = None,
module_equality: str = "structural",
special_space: Mapping[str, SpaceGenerator.SpaceGeneratorType] | None = None,
post_optimization: bool | None = False,
) -> Database:
"""Tune a TIR function or an IRModule of TIR functions.
Parameters
----------
mod : Union[ir.IRModule, tirx.PrimFunc]
The TIR IRModule to tune.
target : Union[str, Target]
The target to tune for.
work_dir : str
The working directory.
max_trials_global : int
The maximum number of trials to run globally.
max_trials_per_task : Optional[int]
The maximum number of trials to run per task.
num_trials_per_iter : int
The number of trials to run per iteration
builder : Builder.BuilderType
The builder.
runner : Runner.RunnerType
The runner.
database : Database.DatabaseType
The database.
cost_model : CostModel.CostModelType
The cost model.
measure_callbacks : MeasureCallback.CallbackListType
The measure callbacks.
task_scheduler : TaskScheduler.TaskSchedulerType
The task scheduler.
space : SpaceGenerator.SpaceGeneratorType
The space generator.
strategy : SearchStrategy.SearchStrategyType
The search strategy.
num_tuning_cores : Union[Literal["physical", "logical"], int]
The number of CPU cores to use during tuning.
seed : Optional[int]
The seed for the random number generator.
module_equality : Optional[str]
A string to specify the module equality testing and hashing method.
special_space : Optional[Mapping[str, SpaceGenerator.SpaceGeneratorType]]
A mapping from task name to a special space generator for that task.
Returns
-------
database : Database
The database with all tuning records
"""
if isinstance(mod, tirx.PrimFunc):
mod = _normalize_mod(mod)
named_tasks: list[tuple[str, tirx.PrimFunc]] = []
for gv, func in mod.functions_items(): # pylint: disable=invalid-name
if isinstance(func, tirx.PrimFunc):
named_tasks.append((gv.name_hint, func))
named_tasks.sort(key=lambda x: x[0])
task_names = [x for x, _ in named_tasks]
tasks: list[TuneContext] = []
for task_name, task_func, logger, rand_state in zip(
task_names,
[x for _, x in named_tasks],
get_loggers_from_work_dir(work_dir, task_names),
fork_seed(seed, n=len(named_tasks)),
):
if special_space and task_name in special_space:
task_space = special_space[task_name]
else:
task_space = space
if task_space is None:
continue
tasks.append(
TuneContext(
mod=task_func,
target=target,
space_generator=task_space,
search_strategy=strategy,
task_name=task_name,
rand_state=rand_state,
num_threads=num_tuning_cores,
logger=logger,
).clone()
)
return tune_tasks(
tasks=tasks,
task_weights=[1.0] * len(tasks),
work_dir=work_dir,
max_trials_global=max_trials_global,
max_trials_per_task=max_trials_per_task,
num_trials_per_iter=num_trials_per_iter,
builder=builder,
runner=runner,
database=database,
cost_model=cost_model,
measure_callbacks=measure_callbacks,
task_scheduler=task_scheduler,
module_equality=module_equality,
post_optimization=post_optimization,
)
@register_global_func("tvm.s_tir.meta_schedule.tune_tir")
def _tune_tir(
mod: ir.IRModule | tirx.PrimFunc,
target: str | Target,
work_dir: str,
max_trials_global: int,
*,
num_trials_per_iter: int = 64,
builder: Builder.BuilderType = "local",
runner: Runner.RunnerType = "local",
database: Database.DatabaseType = "json",
cost_model: CostModel.CostModelType = "xgb",
measure_callbacks: MeasureCallback.CallbackListType = "default",
task_scheduler: TaskScheduler.TaskSchedulerType = "round-robin",
space: SpaceGenerator.SpaceGeneratorType = "post-order-apply",
strategy: SearchStrategy.SearchStrategyType = "evolutionary",
num_tuning_cores: Literal["physical", "logical"] | int = "physical",
seed: int | None = None,
) -> Database:
"""Interface with tuning api to tune a TIR program.
Parameters
----------
mod : Union[ir.IRModule, tirx.PrimFunc]
The TIR function to tune.
target : Union[str, Target]
The target to tune for.
work_dir : str
The working directory.
max_trials_global : int
The maximum number of trials to run globally.
num_trials_per_iter : int
The number of trials to run per iteration
builder : Builder.BuilderType
The builder.
runner : Runner.RunnerType
The runner.
database : Database.DatabaseType
The database.
cost_model : CostModel.CostModelType
The cost model.
measure_callbacks : MeasureCallback.CallbackListType
The measure callbacks.
task_scheduler : TaskScheduler.TaskSchedulerType
The task scheduler.
space : SpaceGenerator.SpaceGeneratorType
The space generator.
strategy : SearchStrategy.SearchStrategyType
The search strategy.
num_tuning_cores : Union[Literal["physical", "logical"], int]
The number of CPU cores to use during tuning.
seed : Optional[int]
The seed for the random number generator.
Returns
-------
ret_mod : IRModule
IRModule
"""
if isinstance(max_trials_global, IntImm):
max_trials_global = int(max_trials_global)
tune_tir(
mod,
target,
work_dir,
max_trials_global,
num_trials_per_iter=num_trials_per_iter,
builder=builder,
runner=runner,
database=database,
cost_model=cost_model,
measure_callbacks=measure_callbacks,
task_scheduler=task_scheduler,
space=space,
strategy=strategy,
num_tuning_cores=num_tuning_cores,
seed=seed,
)
# Return original IRModule
# This pass only makes optimization decision
return mod
def compile_tir(
database: Database,
mod: ir.IRModule | tirx.PrimFunc,
target: Target | str,
) -> _Schedule:
"""Compile a TIR to s_tir.Schedule, according to the records in the database.
Parameters
----------
database : Database
The database of tuning records.
mod : Union[ir.IRModule, tirx.PrimFunc]
The TIR function to tune.
target : Union[str, Target]
The target to tune for.
Returns
-------
sch : s_tir.Schedule
The best schedule found in the database.
"""
mod = _normalize_mod(mod)
if not isinstance(target, Target):
target = Target(target)
return database.query_schedule(mod, target, workload_name="main")