Files
wehub-resource-sync 26446540fa
Lint / lint (push) Waiting to run
CI / MacOS (push) Waiting to run
CI / Windows (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:36:25 +08:00

245 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.
"""Target data structure."""
import tvm_ffi
from tvm_ffi import Map
from tvm_ffi.core import String
from tvm.runtime import Device, Object, convert
from . import _ffi_api
@tvm_ffi.register_object("target.TargetKind")
class TargetKind(Object):
"""Kind of a compilation target"""
@property
def options(self):
"""Returns the dict of available option names and types"""
return dict(_ffi_api.ListTargetKindOptions(self))
@staticmethod
def options_from_name(kind_name: str):
"""Returns the dict of available option names and types from a name of TargetKind"""
return dict(_ffi_api.ListTargetKindOptionsFromName(kind_name))
class TargetFeatures:
def __init__(self, target):
self.target = target
def __getattr__(self, name: str):
return _ffi_api.TargetGetFeature(self.target, name)
@tvm_ffi.register_object("target.Target")
class Target(Object):
"""Target device information, use through TVM API.
Targets can be constructed from:
- A JSON config dictionary: ``Target({"kind": "cuda", "arch": "sm_80"})``
- A tag name: ``Target("nvidia/nvidia-a100")``
- A tag with overrides: ``Target({"tag": "nvidia/nvidia-a100", "l2_cache_size_bytes": 12345})``
- A kind name: ``Target("cuda")``
Use ``target.attrs["key"]`` to access target attributes.
Examples
--------
.. code-block:: python
# From a tag
target = Target("nvidia/nvidia-a100")
# From a tag with attribute overrides
target = Target({"tag": "qcom/hexagon-v68", "vtcm-capacity": 70000})
# From a config dictionary
target = Target({"kind": "cuda", "arch": "sm_80"})
"""
def __init__(self, target, host=None):
"""Construct a TVM target object from
1) Raw target string
2) Target config dict
3) Target tag string
4) Tag with overrides dict
Parameters
----------
target : Union[str, Dict[str, Any]]
Can be one of a literal target string, a json string describing
a configuration, or a dictionary of configuration options.
When using a dictionary or json string to configure target, the
possible values are:
tag : str (optional)
A registered tag name (e.g. ``"nvidia/nvidia-a100"``).
When ``tag`` is present, the tag's base config is loaded and
any additional fields in the dict override the base values.
The ``kind`` field is not needed when ``tag`` is specified.
kind : str (required unless tag is specified)
Which codegen path to use, for example 'llvm' or 'cuda'.
keys : List of str (optional)
A set of strategies that can be dispatched to. When using
"kind=opencl" for example, one could set keys to ["mali", "opencl", "gpu"].
device : str (optional)
A single key that corresponds to the actual device being run on.
This will be effectively appended to the keys.
libs : List of str (optional)
The set of external libraries to use. For example ['cblas', 'mkl'].
system-lib : bool (optional)
If True, build a module that contains self registered functions.
Useful for environments where dynamic loading like dlopen is banned.
mcpu : str (optional)
The specific cpu being run on. Serves only as an annotation.
model : str (optional)
An annotation indicating what model a workload came from.
runtime : str (optional)
An annotation indicating which runtime to use with a workload.
mtriple : str (optional)
The llvm triplet describing the target, for example "arm64-linux-android".
mattr : List of str (optional)
The llvm features to compile with, for example ["+avx512f", "+mmx"].
mfloat-abi : str (optional)
An llvm setting that is one of 'hard' or 'soft' indicating whether to use
hardware or software floating-point operations.
mabi : str (optional)
An llvm setting. Generate code for the specified ABI, for example "lp64d".
host : Union[str, Dict[str, Any]] (optional)
Description for target host. Can be recursive. Similar to target.
host : Optional[Union[str, Dict[str, Any]]]
Similar to target but for target host. Can be one of a literal target host string,
a json string describing a configuration, or a dictionary of configuration options.
When using a dictionary or json string to configure target, the possible values are
same as target.
"""
if isinstance(target, dict | str):
target = convert(target)
if isinstance(host, dict | str):
host = convert(host)
if target is None or not isinstance(target, Map | String | Target | str):
raise ValueError(f"target has to be a string or dictionary. instead get {type(target)}")
if host is not None:
if not isinstance(host, Map | String | Target | str):
raise ValueError("target host has to be a string or dictionary.")
self.__init_handle_by_constructor__(_ffi_api.Target, Target(target), Target(host))
else:
self.__init_handle_by_constructor__(_ffi_api.Target, target)
def __enter__(self):
_ffi_api.TargetEnterScope(self)
return self
def __exit__(self, ptype, value, trace):
_ffi_api.TargetExitScope(self)
def export(self):
return _ffi_api.TargetExport(self)
def with_host(self, host=None):
return _ffi_api.WithHost(self, Target(host))
@staticmethod
def from_device(device: str | Device) -> "Target":
"""Detects Target associated with the given device. If the device does not exist,
there will be an Error.
Parameters
----------
dev : Union[str, Device]
The device to detect the target for.
Supported device types: ["cuda", "metal", "rocm", "vulkan", "opencl", "cpu"]
Returns
-------
target : Target
The detected target.
"""
from .detect_target import ( # pylint: disable=import-outside-toplevel
detect_target_from_device,
)
return detect_target_from_device(device)
@staticmethod
def current(allow_none=True):
"""Returns the current target.
Parameters
----------
allow_none : bool
Whether allow the current target to be none
Raises
------
ValueError if current target is not set.
"""
return _ffi_api.TargetCurrent(allow_none)
@property
def features(self):
return TargetFeatures(self)
def __getattr__(self, name: str):
"""Backward-compatible attribute access for target attrs.
Historically, code accessed target options via attribute syntax
(e.g. ``target.arch``). Newer APIs prefer ``target.attrs["arch"]``.
"""
attrs = self.attrs
if name in attrs:
value = attrs[name]
return str(value) if isinstance(value, String) else value
raise AttributeError(f"'Target' object has no attribute '{name}'")
def get_kind_attr(self, attr_name):
"""Get additional attribute about the target kind.
Parameters
----------
attr_name : str
The attribute name.
Returns
-------
value : object
The attribute value
"""
return _ffi_api.TargetKindGetAttr(self.kind, attr_name)
def get_target_device_type(self):
"""Returns the device_type for this target."""
return _ffi_api.TargetGetDeviceType(self)
@staticmethod
def list_kinds():
"""Returns the list of available target names."""
return list(_ffi_api.ListTargetKinds())
@staticmethod
def target_or_current(target):
"""Returns target, or the current target in the environment if target is None"""
if target is None:
target = Target.current()
if target is None:
raise ValueError("Target is not set in env or passed as argument.")
return target