chore: import upstream snapshot with attribution
Lint / lint (push) Has been cancelled
CI / MacOS (push) Has been cancelled
CI / Windows (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:36:25 +08:00
commit 26446540fa
3151 changed files with 974126 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
# isort: skip_file
# 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 description and codegen module.
TVM uses JSON-based target configuration. Targets can be constructed via:
- A 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 such as
``"arch"``, ``"max_num_threads"``, ``"mcpu"``, ``"libs"``, etc.
Use :py:func:`tvm.target.list_tags` to list all available target tags,
and :py:func:`tvm.target.register_tag` to register new tags.
"""
from .target import Target, TargetKind
from .virtual_device import VirtualDevice
from .tag import list_tags, register_tag
from . import codegen
from . import tag_registry # registers tags on import
+21
View File
@@ -0,0 +1,21 @@
# 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.
"""FFI APIs for tvm.target"""
import tvm_ffi
tvm_ffi.init_ffi_api("target", __name__)
+269
View File
@@ -0,0 +1,269 @@
# 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.
"""Code generation related functions."""
from tvm_ffi import Array
from . import _ffi_api
from .target import Target
def build_module(mod, target):
"""Build IRModule into Module.
Parameters
----------
mod : tvm.IRModule
The ir module.
target : str
The target module type.
Returns
-------
module : runtime.Module
The corressponding module.
"""
target = Target(target) if isinstance(target, str) else target
return _ffi_api.Build(mod, target)
def target_has_features(cpu_features, target=None):
"""Check CPU features for the target's `-mtriple` and `-mcpu` and `-mattr`.
Parameters
----------
target : Target
The TVM target.
cpu_features : str or Array
CPU Feature(s) to check.
Returns
-------
has_features : bool
True if target has the feature(s).
"""
assert isinstance(target, Target) or target is None
assert isinstance(cpu_features, Array | list | tuple | str)
has_feats = True
cpu_features = [cpu_features] if isinstance(cpu_features, str) else cpu_features
for feat in cpu_features:
has_feats &= _ffi_api.target_has_feature(feat, target)
return has_feats
def llvm_lookup_intrinsic_id(name):
"""Lookup LLVM intrinsic id by name.
Parameters
----------
name : str
The name of the intrinsic.
Returns
-------
intrin_id : int
The intrinsic id.
"""
return _ffi_api.llvm_lookup_intrinsic_id(name)
def llvm_get_intrinsic_name(intrin_id: int) -> str:
"""Get the name of an intrinsic for a given id.
Parameters
----------
intrin_id : int
The id of the intrinsic.
Returns
-------
name : str
The name of the intrinsic.
"""
return _ffi_api.llvm_get_intrinsic_name(intrin_id)
def llvm_get_system_x86_vendor():
"""Get system x86 vendor info.
Parameters
----------
Returns
-------
vendor : str
The current system's cpu vendor.
"""
return _ffi_api.llvm_get_system_x86_vendor()
def llvm_get_system_triple():
"""Get system host triple.
Parameters
----------
Returns
-------
triple : str
The current system's triple.
"""
return _ffi_api.llvm_get_system_triple()
def llvm_get_system_cpu():
"""Get system host cpu name.
Parameters
----------
Returns
-------
cpu_name : str
The current system's cpu name.
"""
return _ffi_api.llvm_get_system_cpu()
def llvm_get_targets():
"""Get LLVM target list.
Parameters
----------
Returns
-------
llvm_targets : list[str]
List of available LLVM targets.
"""
return _ffi_api.llvm_get_targets()
def llvm_get_cpu_archlist(target=None):
"""Get CPU architectures for the target's `-mtriple`.
Parameters
----------
target : Target
The TVM target.
Returns
-------
cpu_archlist : list[str]
List of available CPU architectures.
"""
assert isinstance(target, Target) or target is None
return _ffi_api.llvm_get_cpu_archlist(target)
def llvm_get_cpu_features(target=None):
"""Get CPU features for the target's `-mtriple` and `-mcpu` and considering `-mattr`.
Parameters
----------
target : Target
The TVM target.
Returns
-------
cpu_features : list[str]
List of available CPU features.
"""
assert isinstance(target, Target) or target is None
feature_map = _ffi_api.llvm_get_cpu_features(target)
return set(feature_map.keys())
def llvm_cpu_has_features(cpu_features, target=None):
"""Check CPU features for the target's `-mtriple` and `-mcpu` and considering `-mattr`.
Parameters
----------
target : Target
The TVM target.
cpu_features : str or Array
CPU Feature(s) to check.
Returns
-------
has_features : bool
True if target CPU has the feature(s).
"""
assert isinstance(target, Target) or target is None
assert isinstance(cpu_features, Array | list | tuple | str)
has_feats = True
cpu_features = [cpu_features] if isinstance(cpu_features, str) else cpu_features
for feat in cpu_features:
has_feats &= _ffi_api.llvm_cpu_has_feature(feat, target)
return has_feats
def llvm_get_vector_width(target=None):
"""Get vector width from LLVM target's `-mtriple` and `-mcpu` and considering `-mattr`.
Parameters
----------
target : Target
The TVM target.
Returns
-------
vector_width : int
Vector with of target in number of bits, -1 on error.
"""
assert isinstance(target, Target) or target is None
return _ffi_api.llvm_get_vector_width(target)
def llvm_is_valid_cpu(cpu, triple):
"""Check if a CPU name is valid for the given LLVM triple.
Parameters
----------
cpu : str
The CPU name to check (e.g. "apple-m1").
triple : str
The LLVM target triple (e.g. "arm64-apple-macos").
Returns
-------
is_valid : bool
True if the CPU name is recognized by LLVM for the given triple.
"""
return _ffi_api.llvm_is_valid_cpu(cpu, triple)
def llvm_version_major(allow_none=False):
"""Get the major LLVM version.
Parameters
----------
allow_none : bool
Whether do we allow none.
Returns
-------
major : int
The major LLVM version.
"""
try:
return _ffi_api.llvm_version_major()
except AttributeError:
if allow_none:
return None
raise RuntimeError("LLVM version is not available, please check if you built TVM with LLVM")
+85
View File
@@ -0,0 +1,85 @@
# 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.
"""Detect target."""
from collections.abc import Callable
from tvm_ffi import get_global_func
from ..runtime import Device, device
from . import Target
def _detect_cpu(dev: Device) -> Target: # pylint: disable=unused-argument
"""Detect the host CPU architecture."""
return Target(
{
"kind": "llvm",
"mtriple": get_global_func(
"tvm.codegen.llvm.GetDefaultTargetTriple",
allow_missing=False,
)(),
"mcpu": get_global_func(
"tvm.codegen.llvm.GetHostCPUName",
allow_missing=False,
)(),
}
)
SUPPORTED_DEVICE: dict[str, Callable[[Device], Target]] = {
"cpu": _detect_cpu,
}
# Backward-compatible alias for the previous private module-level map.
SUPPORT_DEVICE = SUPPORTED_DEVICE
def register_device_target_detector(device_type: str, detector: Callable[[Device], Target]) -> None:
"""Register target detection for a runtime device type."""
SUPPORTED_DEVICE[device_type] = detector
def detect_target_from_device(dev: 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 are registered by backend hooks.
Returns
-------
target : Target
The detected target.
"""
if isinstance(dev, str):
dev = device(dev)
device_type = Device._DEVICE_TYPE_TO_NAME[dev.dlpack_device_type()]
if device_type not in SUPPORTED_DEVICE:
raise ValueError(
f"Auto detection for device `{device_type}` is not supported. "
f"Currently only supports: {SUPPORTED_DEVICE.keys()}"
)
if not dev.exist:
raise ValueError(
f"Cannot detect device `{dev}`. Please make sure the device and its driver "
"is installed properly, and TVM is compiled with the driver"
)
return SUPPORTED_DEVICE[device_type](dev)
+82
View File
@@ -0,0 +1,82 @@
# 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 dependent intrinsic registration."""
from tvm.ir import register_intrin_lowering
from tvm.tirx import call_pure_extern
def _rule_float_suffix(op):
"""Intrinsic rule: Add float suffix if it is float32.
This is an example intrinsic generation rule.
Parameters
----------
op : Expr
The call expression of original intrinsic.
Returns
-------
ret : Expr
The translated intrinsic rule.
Return same op if no translation is possible.
See Also
--------
register_intrin_lowering : The registration function for intrinsic lowering rule.
"""
name = op.op.name
assert name.startswith("tirx.")
prefix = name[4:]
if op.ty.dtype == "float32":
return call_pure_extern(op.ty, f"{prefix}f", *op.args)
if op.ty.dtype == "float64":
return call_pure_extern(op.ty, prefix, *op.args)
return op
def _rule_float_direct(op):
"""Intrinsic rule: Directly call pure extern function for floats.
This is an example intrinsic generation rule.
Parameters
----------
op : Expr
The call expression of original intrinsic.
Returns
-------
ret : Expr
The translated intrinsic rule.
Return same op if no translation is possible.
See Also
--------
register_intrin_lowering : The registration function for intrinsic lowering rule.
"""
if str(op.ty.dtype).startswith("float"):
return call_pure_extern(op.ty, op.op.name[4:], *op.args)
return None
# opencl pattern for exp
register_intrin_lowering("tirx.exp", target="opencl", f=_rule_float_direct, level=99)
# default pattern for exp
register_intrin_lowering("tirx.exp", target="default", f=_rule_float_suffix, level=99)
+21
View File
@@ -0,0 +1,21 @@
# 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 tags -- re-exported from tag_registry.registry."""
from .tag_registry.registry import list_tags, register_tag
__all__ = ["list_tags", "register_tag"]
@@ -0,0 +1,29 @@
# isort: skip_file
# 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.
"""Python-side target tag registry.
Importing this package registers all Python-defined target tags.
"""
from . import registry
from . import arm_cpu
from . import riscv_cpu
from . import aws_cpu
# Validate all tags at import time
registry.list_tags()
+116
View File
@@ -0,0 +1,116 @@
# 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.
"""ARM CPU target tags."""
from .registry import register_tag
# ---------- Raspberry Pi (self-hosted, with host config) ----------
register_tag(
"raspberry-pi/4b-aarch64",
{
"kind": "llvm",
"mtriple": "aarch64-linux-gnu",
"mcpu": "cortex-a72",
"mattr": ["+neon"],
"num-cores": 4,
"host": {
"kind": "llvm",
"mtriple": "aarch64-linux-gnu",
"mcpu": "cortex-a72",
"mattr": ["+neon"],
"num-cores": 4,
},
},
)
# ---------- ARM boards ----------
def _register_arm_tag(name, config):
base = {"kind": "llvm", "keys": ["arm_cpu", "cpu"], "device": "arm_cpu"}
base.update(config)
register_tag(name, base)
_register_arm_tag(
"arm/pixel2",
{"model": "snapdragon835", "mtriple": "arm64-linux-android", "mattr": ["+neon"]},
)
_register_arm_tag(
"arm/mate10",
{"model": "kirin970", "mtriple": "arm64-linux-android", "mattr": ["+neon"]},
)
_register_arm_tag(
"arm/rasp3b",
{"model": "bcm2837", "mtriple": "armv7l-linux-gnueabihf", "mattr": ["+neon"]},
)
_register_arm_tag(
"arm/rasp4b",
{
"model": "bcm2711",
"mtriple": "armv8l-linux-gnueabihf",
"mattr": ["+neon"],
"mcpu": "cortex-a72",
},
)
_register_arm_tag(
"arm/rasp4b64",
{
"model": "bcm2711",
"mtriple": "aarch64-linux-gnu",
"mattr": ["+neon"],
"mcpu": "cortex-a72",
},
)
_register_arm_tag(
"arm/rk3399",
{"model": "rk3399", "mtriple": "aarch64-linux-gnu", "mattr": ["+neon"]},
)
_register_arm_tag(
"arm/pynq",
{"model": "pynq", "mtriple": "armv7a-linux-eabi", "mattr": ["+neon"]},
)
_register_arm_tag(
"arm/ultra96",
{"model": "ultra96", "mtriple": "aarch64-linux-gnu", "mattr": ["+neon"]},
)
_register_arm_tag(
"arm/beagleai",
{
"model": "beagleai",
"mtriple": "armv7a-linux-gnueabihf",
"mattr": ["+neon", "+vfp4", "+thumb2"],
"mcpu": "cortex-a15",
},
)
_register_arm_tag(
"arm/stm32mp1",
{
"model": "stm32mp1",
"mtriple": "armv7a-linux-gnueabihf",
"mattr": ["+neon", "+vfp4", "+thumb2"],
"mcpu": "cortex-a7",
},
)
_register_arm_tag(
"arm/thunderx",
{
"model": "thunderx",
"mtriple": "aarch64-linux-gnu",
"mattr": ["+neon", "+crc", "+lse"],
"mcpu": "thunderxt88",
},
)
+41
View File
@@ -0,0 +1,41 @@
# 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.
"""AWS CPU instance target tags."""
from .registry import register_tag
def _register_aws_c5(name, cores, arch):
register_tag(
name,
{
"kind": "llvm",
"keys": ["x86", "cpu"],
"mcpu": arch,
"num-cores": cores,
},
)
_register_aws_c5("aws/cpu/c5.large", 1, "skylake-avx512")
_register_aws_c5("aws/cpu/c5.xlarge", 2, "skylake-avx512")
_register_aws_c5("aws/cpu/c5.2xlarge", 4, "skylake-avx512")
_register_aws_c5("aws/cpu/c5.4xlarge", 8, "skylake-avx512")
_register_aws_c5("aws/cpu/c5.9xlarge", 18, "skylake-avx512")
_register_aws_c5("aws/cpu/c5.12xlarge", 24, "cascadelake")
_register_aws_c5("aws/cpu/c5.18xlarge", 36, "skylake-avx512")
_register_aws_c5("aws/cpu/c5.24xlarge", 48, "cascadelake")
@@ -0,0 +1,69 @@
# 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 tag registry functions."""
from typing import Any
from .. import _ffi_api
from ..target import Target
def list_tags() -> dict[str, Target] | None:
"""Returns a dict of tags, which maps each tag name to its corresponding target.
Returns
-------
tag_dict : Optional[Dict[str, Target]]
The dict of tags mapping each tag name to its corresponding target.
None if TVM is built in runtime-only mode.
"""
if hasattr(_ffi_api, "TargetTagListTags"):
return _ffi_api.TargetTagListTags()
return None
def register_tag(name: str, config: dict[str, Any], override: bool = False) -> Target | None:
"""Add a user-defined tag into the target tag registry.
Parameters
----------
name: str
Name of the target, e.g. "nvidia/gtx1080ti"
config : Dict[str, Any]
The config dict used to create the target
override: bool
A boolean flag indicating if overriding existing tags are allowed.
If False and the tag has been registered already, an exception will be thrown.
Returns
-------
target : Optional[Target]
The target corresponding to the tag
None if TVM is built in runtime-only mode.
Examples
--------
.. code-block:: python
register_tag("nvidia/gtx1080ti", config={
"kind": "cuda",
"arch": "sm_61",
})
"""
if hasattr(_ffi_api, "TargetTagAddTag"):
return _ffi_api.TargetTagAddTag(name, config, override)
return None
@@ -0,0 +1,84 @@
# 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.
"""RISC-V CPU target tags (from old riscv_cpu() translation table)."""
from .registry import register_tag
def _register_riscv_tag(name, config):
base = {"kind": "llvm", "keys": ["riscv_cpu", "cpu"], "device": "riscv_cpu"}
base.update(config)
register_tag(name, base)
_register_riscv_tag(
"riscv/sifive-e31",
{
"model": "sifive-e31",
"mtriple": "riscv32-unknown-linux-gnu",
"mcpu": "sifive-e31",
"mabi": "ilp32",
},
)
_register_riscv_tag(
"riscv/sifive-e76",
{
"model": "sifive-e76",
"mtriple": "riscv32-unknown-linux-gnu",
"mcpu": "sifive-e76",
"mabi": "ilp32",
},
)
_register_riscv_tag(
"riscv/sifive-u54",
{
"model": "sifive-u54",
"mtriple": "riscv64-unknown-linux-gnu",
"mcpu": "sifive-u54",
"mabi": "lp64d",
},
)
_register_riscv_tag(
"riscv/sifive-u74",
{
"model": "sifive-u74",
"mtriple": "riscv64-unknown-linux-gnu",
"mcpu": "sifive-u74",
"mabi": "lp64d",
},
)
_register_riscv_tag(
"riscv/licheepi3a",
{
"num-cores": 8,
"mtriple": "riscv64-unknown-linux-gnu",
"mcpu": "spacemit-x60",
"mfloat-abi": "hard",
"mabi": "lp64d",
},
)
_register_riscv_tag(
"riscv/spacemit-k3",
{
"num-cores": 8,
"mtriple": "riscv64-unknown-linux-gnu",
"mcpu": "spacemit-x100",
"mfloat-abi": "hard",
"mabi": "lp64d",
},
)
+244
View File
@@ -0,0 +1,244 @@
# 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
+39
View File
@@ -0,0 +1,39 @@
# 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.
# ruff: noqa: F821
"""Python bindings for creating VirtualDevices."""
import tvm_ffi
from . import _ffi_api
@tvm_ffi.register_object("target.VirtualDevice")
class VirtualDevice(tvm_ffi.core.Object):
"""A compile time representation for where data is to be stored at runtime,
and how to compile code to compute it."""
def __init__(self, device=None, target=None, memory_scope="") -> None:
if device is None:
# The 'unconstrained' device has device type -1 and device id -1.
device = tvm.device(-1, -1)
self.__init_handle_by_constructor__(
_ffi_api.VirtualDevice_ForDeviceTargetAndMemoryScope, device, target, memory_scope
)
def dlpack_device_type(self) -> int:
return self.device_type_int