From 940aeab667ad771ccc32d921db5e18355c1f81a2 Mon Sep 17 00:00:00 2001 From: Xiyou Zhou Date: Wed, 10 Feb 2021 15:10:40 -0800 Subject: [PATCH 01/10] Add target host field in Target --- include/tvm/target/target.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/tvm/target/target.h b/include/tvm/target/target.h index 2abdb558baf8..81cab7cc37e3 100644 --- a/include/tvm/target/target.h +++ b/include/tvm/target/target.h @@ -44,6 +44,8 @@ class TargetNode : public Object { public: /*! \brief The kind of the target device */ TargetKind kind; + /*! \brief Target host information of the target device */ + Optional host; /*! \brief Tag of the the target, can be empty */ String tag; /*! \brief Keys for this target */ @@ -64,6 +66,7 @@ class TargetNode : public Object { v->Visit("tag", &tag); v->Visit("keys", &keys); v->Visit("attrs", &attrs); + v->Visit("host", &host); } /*! From 3c57ce662aebbf2d1784e3418238662f0dc9de9f Mon Sep 17 00:00:00 2001 From: Xiyou Zhou Date: Fri, 12 Feb 2021 15:16:33 -0800 Subject: [PATCH 02/10] Add host as a config field to target --- include/tvm/target/target.h | 5 +++++ src/target/target.cc | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/include/tvm/target/target.h b/include/tvm/target/target.h index 81cab7cc37e3..f610a4c353ac 100644 --- a/include/tvm/target/target.h +++ b/include/tvm/target/target.h @@ -141,6 +141,11 @@ class Target : public ObjectRef { * \return The target that is the current context. The target may not be defined if * allow_not_defined is true. */ + TVM_DLL explicit Target(Target target, Target host); + /*! + * \brief Construct a Target given target and host + * \return The Target with given target and host context information + */ TVM_DLL static tvm::Target Current(bool allow_not_defined = true); TVM_DEFINE_OBJECT_REF_METHODS(Target, ObjectRef, TargetNode); diff --git a/src/target/target.cc b/src/target/target.cc index e44a15c3ff59..fe727ad53507 100644 --- a/src/target/target.cc +++ b/src/target/target.cc @@ -527,6 +527,7 @@ ObjectPtr TargetInternal::FromConfig(std::unordered_map target = make_object(); // parse 'kind' if (config.count(kKind)) { @@ -599,6 +600,13 @@ ObjectPtr TargetInternal::FromConfig(std::unordered_maphost = PackedFunc(ConstructorDispatcher)(config[kHost]).AsObjectRef(); + config.erase(kHost); + } else { + target->host = NullOpt; + } // set default attribute values if they do not exist for (const auto& kv : target->kind->key2default_) { if (!attrs.count(kv.first)) { @@ -614,6 +622,15 @@ ObjectPtr TargetInternal::FromConfig(std::unordered_map n = make_object(*target.get()); + if (n->host.defined()) + throw dmlc::Error(": Error when adding target host to target already with host"); + // add target host into host field + n->host = std::move(host); + data_ = std::move(n); +} + /********** Registry **********/ TVM_REGISTER_GLOBAL("target.Target").set_body(TargetInternal::ConstructorDispatcher); From a969faea8fd393168fa0e5a5a3b184d417992088 Mon Sep 17 00:00:00 2001 From: Xiyou Zhou Date: Fri, 12 Feb 2021 17:44:16 -0800 Subject: [PATCH 03/10] Add target host support for Python api --- include/tvm/target/target.h | 18 ++++++++++++++++-- python/tvm/target/target.py | 17 +++++++++++++++-- src/target/target.cc | 38 ++++++++++++++++++++++++++++--------- 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/include/tvm/target/target.h b/include/tvm/target/target.h index f610a4c353ac..59f5df9f4a27 100644 --- a/include/tvm/target/target.h +++ b/include/tvm/target/target.h @@ -125,14 +125,28 @@ class Target : public ObjectRef { TVM_DLL explicit Target(std::nullptr_t) { data_ = nullptr; } /*! * \brief Construct a Target given a string - * \param tag_or_config_or_target_str the string to parse + * \param tag_or_config_or_target_str the string to parse for target */ TVM_DLL explicit Target(const String& tag_or_config_or_target_str); + /*! + * \brief Construct a Target given a string + * \param tag_or_config_or_target_str the string to parse for target + * \param host_tag_or_config_or_host_str the string to parse for target host + */ + TVM_DLL explicit Target(const String& tag_or_config_or_target_str, + const String& host_tag_or_config_or_host_str); /*! * \brief Construct a Target using a JSON-like configuration - * \param config The JSON-like configuration + * \param config The JSON-like configuration for target */ TVM_DLL explicit Target(const Map& config); + /*! + * \brief Construct a Target using a JSON-like configuration + * \param config The JSON-like configuration for target + * \param host_config The JSON-like configuration for target host + */ + TVM_DLL explicit Target(const Map& config, + const Map& host_config); /*! * \brief Get the current target context from thread local storage. * \param allow_not_defined If the context stack is empty and this is set to true, an diff --git a/python/tvm/target/target.py b/python/tvm/target/target.py index 0ebf31ae6462..51ae6bec9aef 100644 --- a/python/tvm/target/target.py +++ b/python/tvm/target/target.py @@ -46,7 +46,7 @@ class Target(Object): - :py:func:`tvm.target.intel_graphics` create Intel Graphics target """ - def __init__(self, tag_or_str_or_dict): + def __init__(self, tag_or_str_or_dict, host_tag_or_str_or_dict=None): """Construct a TVM target object from 1) Raw target string 2) Target config dict @@ -86,10 +86,23 @@ def __init__(self, tag_or_str_or_dict): mfloat-abi : str (optional) An llvm setting that is one of 'hard' or 'soft' indicating whether to use hardware or software floating-point operations. + host_tag_or_str_or_dict : Union[str, Dict[str, Any]] + Similar to tag_or_str_or_dict 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 tag_or_str_or_dict. """ if not isinstance(tag_or_str_or_dict, (dict, str, Target)): raise ValueError("target has to be a string or dictionary.") - self.__init_handle_by_constructor__(_ffi_api.Target, tag_or_str_or_dict) + if host_tag_or_str_or_dict is not None: + if not isinstance(host_tag_or_str_or_dict, (dict, str, Target)): + raise ValueError("target host has to be a string or dictionary.") + else: + self.__init_handle_by_constructor__( + _ffi_api.Target, tag_or_str_or_dict, host_tag_or_str_or_dict + ) + else: + self.__init_handle_by_constructor__(_ffi_api.Target, tag_or_str_or_dict) def __enter__(self): _ffi_api.TargetEnterScope(self) diff --git a/src/target/target.cc b/src/target/target.cc index fe727ad53507..20722193fade 100644 --- a/src/target/target.cc +++ b/src/target/target.cc @@ -362,6 +362,14 @@ Target::Target(const String& tag_or_config_or_target_str) { data_ = std::move(target); } +Target::Target(const String& tag_or_config_or_target_str, + const String& host_tag_or_config_or_host_str) { + ObjectPtr n = make_object( + *Target(Target(tag_or_config_or_target_str), + Target(host_tag_or_config_or_host_str)).get()); + data_ = std::move(n); +} + Target::Target(const Map& config) { ObjectPtr target; try { @@ -373,6 +381,22 @@ Target::Target(const Map& config) { data_ = std::move(target); } +Target::Target(const Map& config, + const Map& host_config) { + ObjectPtr n = make_object( + *Target(Target(config), Target(host_config)).get()); + data_ = std::move(n); +} + +Target::Target(Target target, Target host) { + ObjectPtr n = make_object(*target.get()); + if (n->host.defined()) + throw dmlc::Error(": Error when adding target host to target already with host"); + // add target host into host field + n->host = std::move(host); + data_ = std::move(n); +} + std::vector TargetNode::GetKeys() const { std::vector result; for (auto& expr : keys) { @@ -456,6 +480,11 @@ void TargetInternal::ConstructorDispatcher(TVMArgs args, TVMRetValue* rv) { << runtime::ArgTypeCode2Str(arg.type_code()); } return; + } else if (args.num_args == 2) { + const auto& argt = args[0], argh = args[1]; + auto func = PackedFunc(ConstructorDispatcher); + *rv = Target(func(argt).AsObjectRef(), func(argh).AsObjectRef()); + return; } LOG(FATAL) << "ValueError: Invalid number of arguments. Expect 1, but gets: " << args.num_args; } @@ -622,15 +651,6 @@ ObjectPtr TargetInternal::FromConfig(std::unordered_map n = make_object(*target.get()); - if (n->host.defined()) - throw dmlc::Error(": Error when adding target host to target already with host"); - // add target host into host field - n->host = std::move(host); - data_ = std::move(n); -} - /********** Registry **********/ TVM_REGISTER_GLOBAL("target.Target").set_body(TargetInternal::ConstructorDispatcher); From 0d5d6d8979458d0fca55164d0220df7538786ac9 Mon Sep 17 00:00:00 2001 From: Xiyou Zhou Date: Tue, 16 Feb 2021 19:01:47 -0800 Subject: [PATCH 04/10] Add unit tests --- python/tvm/target/target.py | 2 + src/target/target_kind.cc | 24 ++++++++-- tests/python/unittest/test_target_target.py | 49 ++++++++++++++++++--- 3 files changed, 64 insertions(+), 11 deletions(-) diff --git a/python/tvm/target/target.py b/python/tvm/target/target.py index 51ae6bec9aef..ec6926ef054c 100644 --- a/python/tvm/target/target.py +++ b/python/tvm/target/target.py @@ -86,6 +86,8 @@ def __init__(self, tag_or_str_or_dict, host_tag_or_str_or_dict=None): mfloat-abi : str (optional) An llvm setting that is one of 'hard' or 'soft' indicating whether to use hardware or software floating-point operations. + host : Union[str, Dict[str, Any]] (optional) + Description for target host. Can be recursive. Similar to tag_or_str_or_dict. host_tag_or_str_or_dict : Union[str, Dict[str, Any]] Similar to tag_or_str_or_dict but for target host. Can be one of a literal target host string, a json string describing a configuration, or a dictionary of diff --git a/src/target/target_kind.cc b/src/target/target_kind.cc index cee708f80b5a..57b232b2190f 100644 --- a/src/target/target_kind.cc +++ b/src/target/target_kind.cc @@ -214,6 +214,7 @@ TVM_REGISTER_TARGET_KIND("llvm", kDLCPU) .add_attr_option("system-lib") .add_attr_option("runtime") .add_attr_option("link-params", Bool(false)) + .add_attr_option("host") .set_default_keys({"cpu"}); TVM_REGISTER_TARGET_KIND("c", kDLCPU) @@ -222,6 +223,7 @@ TVM_REGISTER_TARGET_KIND("c", kDLCPU) .add_attr_option("runtime") .add_attr_option("mcpu") .add_attr_option("march") + .add_attr_option("host") .set_default_keys({"cpu"}); TVM_REGISTER_TARGET_KIND("cuda", kDLGPU) @@ -233,6 +235,7 @@ TVM_REGISTER_TARGET_KIND("cuda", kDLGPU) .add_attr_option("shared_memory_per_block") .add_attr_option("registers_per_block") .add_attr_option("max_threads_per_block") + .add_attr_option("host") .set_default_keys({"cuda", "gpu"}); TVM_REGISTER_TARGET_KIND("nvptx", kDLGPU) @@ -241,6 +244,7 @@ TVM_REGISTER_TARGET_KIND("nvptx", kDLGPU) .add_attr_option("system-lib") .add_attr_option("max_num_threads", Integer(1024)) .add_attr_option("thread_warp_size", Integer(32)) + .add_attr_option("host") .set_default_keys({"cuda", "gpu"}) .set_attrs_preprocessor(UpdateNVPTXAttrs); @@ -250,6 +254,7 @@ TVM_REGISTER_TARGET_KIND("rocm", kDLROCM) .add_attr_option("system-lib") .add_attr_option("max_num_threads", Integer(256)) .add_attr_option("thread_warp_size", Integer(64)) + .add_attr_option("host") .set_default_keys({"rocm", "gpu"}) .set_attrs_preprocessor(UpdateROCmAttrs); @@ -257,33 +262,40 @@ TVM_REGISTER_TARGET_KIND("opencl", kDLOpenCL) .add_attr_option("system-lib") .add_attr_option("max_num_threads", Integer(256)) .add_attr_option("thread_warp_size") + .add_attr_option("host") .set_default_keys({"opencl", "gpu"}); TVM_REGISTER_TARGET_KIND("metal", kDLMetal) .add_attr_option("system-lib") .add_attr_option("max_num_threads", Integer(256)) + .add_attr_option("host") .set_default_keys({"metal", "gpu"}); TVM_REGISTER_TARGET_KIND("vulkan", kDLVulkan) .add_attr_option("system-lib") .add_attr_option("max_num_threads", Integer(256)) + .add_attr_option("host") .set_default_keys({"vulkan", "gpu"}); TVM_REGISTER_TARGET_KIND("webgpu", kDLWebGPU) .add_attr_option("system-lib") .add_attr_option("max_num_threads", Integer(256)) + .add_attr_option("host") .set_default_keys({"webgpu", "gpu"}); TVM_REGISTER_TARGET_KIND("sdaccel", kDLOpenCL) .add_attr_option("system-lib") + .add_attr_option("host") .set_default_keys({"sdaccel", "hls"}); TVM_REGISTER_TARGET_KIND("aocl", kDLAOCL) .add_attr_option("system-lib") + .add_attr_option("host") .set_default_keys({"aocl", "hls"}); TVM_REGISTER_TARGET_KIND("aocl_sw_emu", kDLAOCL) .add_attr_option("system-lib") + .add_attr_option("host") .set_default_keys({"aocl", "hls"}); TVM_REGISTER_TARGET_KIND("hexagon", kDLHexagon) @@ -292,19 +304,23 @@ TVM_REGISTER_TARGET_KIND("hexagon", kDLHexagon) .add_attr_option("mtriple") .add_attr_option("system-lib") .add_attr_option>("llvm-options") + .add_attr_option("host") .set_default_keys({"hexagon"}); TVM_REGISTER_TARGET_KIND("stackvm", kDLCPU) // line break - .add_attr_option("system-lib"); + .add_attr_option("system-lib") + .add_attr_option("host"); TVM_REGISTER_TARGET_KIND("ext_dev", kDLExtDev) // line break - .add_attr_option("system-lib"); + .add_attr_option("system-lib") + .add_attr_option("host"); TVM_REGISTER_TARGET_KIND("hybrid", kDLCPU) // line break - .add_attr_option("system-lib"); + .add_attr_option("system-lib") + .add_attr_option("host"); TVM_REGISTER_TARGET_KIND("composite", kDLCPU) - .add_attr_option("target_host") + .add_attr_option("host") .add_attr_option>("devices"); } // namespace tvm diff --git a/tests/python/unittest/test_target_target.py b/tests/python/unittest/test_target_target.py index 973f14958d9a..d35b3bac7903 100644 --- a/tests/python/unittest/test_target_target.py +++ b/tests/python/unittest/test_target_target.py @@ -16,6 +16,7 @@ # under the License. import json import tvm +import pytest from tvm import te from tvm.target import cuda, rocm, mali, intel_graphics, arm_cpu, vta, bifrost, hexagon @@ -113,18 +114,14 @@ def test_config_map(): attributes fails as expected. """ target_config = {"kind": "llvm", "libs": {"a": "b", "c": "d"}} - failed = False - try: + with pytest.raises(ValueError): tvm.target.Target(target_config) - except ValueError: - failed = True - assert failed def test_composite_target(): - tgt = tvm.target.Target("composite --target_host=llvm --devices=cuda,opencl") + tgt = tvm.target.Target("composite --host=llvm --devices=cuda,opencl") assert tgt.kind.name == "composite" - assert tgt.attrs["target_host"].kind.name == "llvm" + assert tgt.attrs["host"].kind.name == "llvm" assert len(tgt.attrs["devices"]) == 2 cuda_device, opencl_device = tgt.attrs["devices"] assert cuda_device.kind.name == "cuda" @@ -151,6 +148,44 @@ def test_target_tag_1(): assert tgt.attrs["registers_per_block"] == 32768 +def test_target_host_tags(): + tgt = tvm.target.Target("nvidia/jetson-nano", "nvidia/geforce-rtx-2080-ti") + assert tgt.kind.name == "cuda" + assert tgt.attrs["arch"] == "sm_53" + assert tgt.attrs["shared_memory_per_block"] == 49152 + assert tgt.attrs["max_threads_per_block"] == 1024 + assert tgt.attrs["thread_warp_size"] == 32 + assert tgt.attrs["registers_per_block"] == 32768 + assert tgt.host.kind.name == "cuda" + assert tgt.host.attrs["arch"] == "sm_75" + assert tgt.host.attrs["shared_memory_per_block"] == 49152 + assert tgt.host.attrs["max_threads_per_block"] == 1024 + assert tgt.host.attrs["thread_warp_size"] == 32 + assert tgt.host.attrs["registers_per_block"] == 65536 + + +def test_target_host_tag_dict(): + tgt = tvm.target.Target("nvidia/jetson-nano", {"kind": "llvm"}) + assert tgt.kind.name == "cuda" + assert tgt.attrs["arch"] == "sm_53" + assert tgt.attrs["shared_memory_per_block"] == 49152 + assert tgt.attrs["max_threads_per_block"] == 1024 + assert tgt.attrs["thread_warp_size"] == 32 + assert tgt.attrs["registers_per_block"] == 32768 + assert tgt.host.kind.name == "llvm" + + +def test_target_host_single_dict(): + tgt = tvm.target.Target({"kind": "llvm", "host": "nvidia/jetson-nano"}) + assert tgt.kind.name == "llvm" + assert tgt.host.kind.name == "cuda" + assert tgt.host.attrs["arch"] == "sm_53" + assert tgt.host.attrs["shared_memory_per_block"] == 49152 + assert tgt.host.attrs["max_threads_per_block"] == 1024 + assert tgt.host.attrs["thread_warp_size"] == 32 + assert tgt.host.attrs["registers_per_block"] == 32768 + + if __name__ == "__main__": test_target_dispatch() test_target_string_parse() From 4c3a3448b7915d1939faed7533f9813400bd1805 Mon Sep 17 00:00:00 2001 From: Xiyou Zhou Date: Tue, 16 Feb 2021 19:46:18 -0800 Subject: [PATCH 05/10] Adjust format for cpplint --- include/tvm/target/target.h | 6 +++--- src/target/target.cc | 12 +++++------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/include/tvm/target/target.h b/include/tvm/target/target.h index 59f5df9f4a27..d34c34142076 100644 --- a/include/tvm/target/target.h +++ b/include/tvm/target/target.h @@ -134,19 +134,19 @@ class Target : public ObjectRef { * \param host_tag_or_config_or_host_str the string to parse for target host */ TVM_DLL explicit Target(const String& tag_or_config_or_target_str, - const String& host_tag_or_config_or_host_str); + const String& host_tag_or_config_or_host_str); /*! * \brief Construct a Target using a JSON-like configuration * \param config The JSON-like configuration for target */ TVM_DLL explicit Target(const Map& config); - /*! + /*! * \brief Construct a Target using a JSON-like configuration * \param config The JSON-like configuration for target * \param host_config The JSON-like configuration for target host */ TVM_DLL explicit Target(const Map& config, - const Map& host_config); + const Map& host_config); /*! * \brief Get the current target context from thread local storage. * \param allow_not_defined If the context stack is empty and this is set to true, an diff --git a/src/target/target.cc b/src/target/target.cc index 20722193fade..bfd4128e16c5 100644 --- a/src/target/target.cc +++ b/src/target/target.cc @@ -365,8 +365,7 @@ Target::Target(const String& tag_or_config_or_target_str) { Target::Target(const String& tag_or_config_or_target_str, const String& host_tag_or_config_or_host_str) { ObjectPtr n = make_object( - *Target(Target(tag_or_config_or_target_str), - Target(host_tag_or_config_or_host_str)).get()); + *Target(Target(tag_or_config_or_target_str), Target(host_tag_or_config_or_host_str)).get()); data_ = std::move(n); } @@ -381,10 +380,9 @@ Target::Target(const Map& config) { data_ = std::move(target); } -Target::Target(const Map& config, - const Map& host_config) { - ObjectPtr n = make_object( - *Target(Target(config), Target(host_config)).get()); +Target::Target(const Map& config, const Map& host_config) { + ObjectPtr n = + make_object(*Target(Target(config), Target(host_config)).get()); data_ = std::move(n); } @@ -481,7 +479,7 @@ void TargetInternal::ConstructorDispatcher(TVMArgs args, TVMRetValue* rv) { } return; } else if (args.num_args == 2) { - const auto& argt = args[0], argh = args[1]; + const auto &argt = args[0], &argh = args[1]; auto func = PackedFunc(ConstructorDispatcher); *rv = Target(func(argt).AsObjectRef(), func(argh).AsObjectRef()); return; From a1cc2c2ec4aec2adb6f6b70885ff444b23e8bb33 Mon Sep 17 00:00:00 2001 From: Xiyou Zhou Date: Tue, 16 Feb 2021 19:57:04 -0800 Subject: [PATCH 06/10] Remove unnecessary after in Python file --- python/tvm/target/target.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/python/tvm/target/target.py b/python/tvm/target/target.py index 5e393e477482..8dbf9808d334 100644 --- a/python/tvm/target/target.py +++ b/python/tvm/target/target.py @@ -99,10 +99,9 @@ def __init__(self, tag_or_str_or_dict, host_tag_or_str_or_dict=None): if host_tag_or_str_or_dict is not None: if not isinstance(host_tag_or_str_or_dict, (dict, str, Target)): raise ValueError("target host has to be a string or dictionary.") - else: - self.__init_handle_by_constructor__( - _ffi_api.Target, tag_or_str_or_dict, host_tag_or_str_or_dict - ) + self.__init_handle_by_constructor__( + _ffi_api.Target, tag_or_str_or_dict, host_tag_or_str_or_dict + ) else: self.__init_handle_by_constructor__(_ffi_api.Target, tag_or_str_or_dict) From a1cb8812f95b04ebb3331533e1b6dc4ec6055bb7 Mon Sep 17 00:00:00 2001 From: Xiyou Zhou Date: Wed, 17 Feb 2021 15:43:25 -0800 Subject: [PATCH 07/10] Remove redundancy and add param description --- include/tvm/target/target.h | 18 +++---------- include/tvm/target/target_kind.h | 3 ++- python/tvm/target/target.py | 6 ++--- src/target/target.cc | 30 ++++++++------------- src/target/target_kind.cc | 23 +++------------- tests/python/unittest/test_target_target.py | 17 ++++++++++++ 6 files changed, 38 insertions(+), 59 deletions(-) diff --git a/include/tvm/target/target.h b/include/tvm/target/target.h index d34c34142076..add0547a0793 100644 --- a/include/tvm/target/target.h +++ b/include/tvm/target/target.h @@ -44,7 +44,7 @@ class TargetNode : public Object { public: /*! \brief The kind of the target device */ TargetKind kind; - /*! \brief Target host information of the target device */ + /*! \brief Target host information, must be Target type */ Optional host; /*! \brief Tag of the the target, can be empty */ String tag; @@ -128,25 +128,11 @@ class Target : public ObjectRef { * \param tag_or_config_or_target_str the string to parse for target */ TVM_DLL explicit Target(const String& tag_or_config_or_target_str); - /*! - * \brief Construct a Target given a string - * \param tag_or_config_or_target_str the string to parse for target - * \param host_tag_or_config_or_host_str the string to parse for target host - */ - TVM_DLL explicit Target(const String& tag_or_config_or_target_str, - const String& host_tag_or_config_or_host_str); /*! * \brief Construct a Target using a JSON-like configuration * \param config The JSON-like configuration for target */ TVM_DLL explicit Target(const Map& config); - /*! - * \brief Construct a Target using a JSON-like configuration - * \param config The JSON-like configuration for target - * \param host_config The JSON-like configuration for target host - */ - TVM_DLL explicit Target(const Map& config, - const Map& host_config); /*! * \brief Get the current target context from thread local storage. * \param allow_not_defined If the context stack is empty and this is set to true, an @@ -158,6 +144,8 @@ class Target : public ObjectRef { TVM_DLL explicit Target(Target target, Target host); /*! * \brief Construct a Target given target and host + * \param target The Target typed object with host field undefined for target + * \param host The Target typed object for target host * \return The Target with given target and host context information */ TVM_DLL static tvm::Target Current(bool allow_not_defined = true); diff --git a/include/tvm/target/target_kind.h b/include/tvm/target/target_kind.h index 72c41c6f4647..e7da2dd413a0 100644 --- a/include/tvm/target/target_kind.h +++ b/include/tvm/target/target_kind.h @@ -376,7 +376,8 @@ inline TargetKindRegEntry& TargetKindRegEntry::set_name() { .add_attr_option("tag") \ .add_attr_option("device") \ .add_attr_option("model") \ - .add_attr_option>("libs") + .add_attr_option>("libs") \ + .add_attr_option("host") } // namespace tvm diff --git a/python/tvm/target/target.py b/python/tvm/target/target.py index 8dbf9808d334..8c60260e640a 100644 --- a/python/tvm/target/target.py +++ b/python/tvm/target/target.py @@ -88,7 +88,7 @@ def __init__(self, tag_or_str_or_dict, host_tag_or_str_or_dict=None): hardware or software floating-point operations. host : Union[str, Dict[str, Any]] (optional) Description for target host. Can be recursive. Similar to tag_or_str_or_dict. - host_tag_or_str_or_dict : Union[str, Dict[str, Any]] + host_tag_or_str_or_dict : Optional[Union[str, Dict[str, Any]]] Similar to tag_or_str_or_dict 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, @@ -97,10 +97,8 @@ def __init__(self, tag_or_str_or_dict, host_tag_or_str_or_dict=None): if not isinstance(tag_or_str_or_dict, (dict, str, Target)): raise ValueError("target has to be a string or dictionary.") if host_tag_or_str_or_dict is not None: - if not isinstance(host_tag_or_str_or_dict, (dict, str, Target)): - raise ValueError("target host has to be a string or dictionary.") self.__init_handle_by_constructor__( - _ffi_api.Target, tag_or_str_or_dict, host_tag_or_str_or_dict + _ffi_api.Target, Target(tag_or_str_or_dict), Target(host_tag_or_str_or_dict) ) else: self.__init_handle_by_constructor__(_ffi_api.Target, tag_or_str_or_dict) diff --git a/src/target/target.cc b/src/target/target.cc index bfd4128e16c5..5c97da3fbef1 100644 --- a/src/target/target.cc +++ b/src/target/target.cc @@ -362,13 +362,6 @@ Target::Target(const String& tag_or_config_or_target_str) { data_ = std::move(target); } -Target::Target(const String& tag_or_config_or_target_str, - const String& host_tag_or_config_or_host_str) { - ObjectPtr n = make_object( - *Target(Target(tag_or_config_or_target_str), Target(host_tag_or_config_or_host_str)).get()); - data_ = std::move(n); -} - Target::Target(const Map& config) { ObjectPtr target; try { @@ -380,16 +373,10 @@ Target::Target(const Map& config) { data_ = std::move(target); } -Target::Target(const Map& config, const Map& host_config) { - ObjectPtr n = - make_object(*Target(Target(config), Target(host_config)).get()); - data_ = std::move(n); -} - Target::Target(Target target, Target host) { ObjectPtr n = make_object(*target.get()); - if (n->host.defined()) - throw dmlc::Error(": Error when adding target host to target already with host"); + CHECK(!n->host.defined()) << + "ValueError: Adding a host to a target whose host field has been defined"; // add target host into host field n->host = std::move(host); data_ = std::move(n); @@ -479,12 +466,17 @@ void TargetInternal::ConstructorDispatcher(TVMArgs args, TVMRetValue* rv) { } return; } else if (args.num_args == 2) { - const auto &argt = args[0], &argh = args[1]; - auto func = PackedFunc(ConstructorDispatcher); - *rv = Target(func(argt).AsObjectRef(), func(argh).AsObjectRef()); + if (args[0].IsObjectRef() && args[1].IsObjectRef()) { + Target target = args[0]; + Target host = args[1]; + *rv = Target(target, host); + } else { + LOG(FATAL) << "ValueError: Invalid type of arguments. Expect 2 Target arguments."; + } return; } - LOG(FATAL) << "ValueError: Invalid number of arguments. Expect 1, but gets: " << args.num_args; + LOG(FATAL) << "ValueError: Invalid number of arguments. Expect 1 or 2, but gets: " + << args.num_args; } ObjectPtr TargetInternal::FromString(const String& tag_or_config_or_target_str) { diff --git a/src/target/target_kind.cc b/src/target/target_kind.cc index 17378e27ed2b..863d99993f4a 100644 --- a/src/target/target_kind.cc +++ b/src/target/target_kind.cc @@ -219,7 +219,6 @@ TVM_REGISTER_TARGET_KIND("llvm", kDLCPU) .add_attr_option("system-lib") .add_attr_option("runtime") .add_attr_option("link-params", Bool(false)) - .add_attr_option("host") .set_default_keys({"cpu"}); TVM_REGISTER_TARGET_KIND("c", kDLCPU) @@ -228,7 +227,6 @@ TVM_REGISTER_TARGET_KIND("c", kDLCPU) .add_attr_option("runtime") .add_attr_option("mcpu") .add_attr_option("march") - .add_attr_option("host") .set_default_keys({"cpu"}); TVM_REGISTER_TARGET_KIND("cuda", kDLGPU) @@ -240,7 +238,6 @@ TVM_REGISTER_TARGET_KIND("cuda", kDLGPU) .add_attr_option("shared_memory_per_block") .add_attr_option("registers_per_block") .add_attr_option("max_threads_per_block") - .add_attr_option("host") .set_default_keys({"cuda", "gpu"}); TVM_REGISTER_TARGET_KIND("nvptx", kDLGPU) @@ -249,7 +246,6 @@ TVM_REGISTER_TARGET_KIND("nvptx", kDLGPU) .add_attr_option("system-lib") .add_attr_option("max_num_threads", Integer(1024)) .add_attr_option("thread_warp_size", Integer(32)) - .add_attr_option("host") .set_default_keys({"cuda", "gpu"}) .set_attrs_preprocessor(UpdateNVPTXAttrs); @@ -259,7 +255,6 @@ TVM_REGISTER_TARGET_KIND("rocm", kDLROCM) .add_attr_option("system-lib") .add_attr_option("max_num_threads", Integer(256)) .add_attr_option("thread_warp_size", Integer(64)) - .add_attr_option("host") .set_default_keys({"rocm", "gpu"}) .set_attrs_preprocessor(UpdateROCmAttrs); @@ -267,40 +262,33 @@ TVM_REGISTER_TARGET_KIND("opencl", kDLOpenCL) .add_attr_option("system-lib") .add_attr_option("max_num_threads", Integer(256)) .add_attr_option("thread_warp_size") - .add_attr_option("host") .set_default_keys({"opencl", "gpu"}); TVM_REGISTER_TARGET_KIND("metal", kDLMetal) .add_attr_option("system-lib") .add_attr_option("max_num_threads", Integer(256)) - .add_attr_option("host") .set_default_keys({"metal", "gpu"}); TVM_REGISTER_TARGET_KIND("vulkan", kDLVulkan) .add_attr_option("system-lib") .add_attr_option("max_num_threads", Integer(256)) - .add_attr_option("host") .set_default_keys({"vulkan", "gpu"}); TVM_REGISTER_TARGET_KIND("webgpu", kDLWebGPU) .add_attr_option("system-lib") .add_attr_option("max_num_threads", Integer(256)) - .add_attr_option("host") .set_default_keys({"webgpu", "gpu"}); TVM_REGISTER_TARGET_KIND("sdaccel", kDLOpenCL) .add_attr_option("system-lib") - .add_attr_option("host") .set_default_keys({"sdaccel", "hls"}); TVM_REGISTER_TARGET_KIND("aocl", kDLAOCL) .add_attr_option("system-lib") - .add_attr_option("host") .set_default_keys({"aocl", "hls"}); TVM_REGISTER_TARGET_KIND("aocl_sw_emu", kDLAOCL) .add_attr_option("system-lib") - .add_attr_option("host") .set_default_keys({"aocl", "hls"}); TVM_REGISTER_TARGET_KIND("hexagon", kDLHexagon) @@ -309,23 +297,18 @@ TVM_REGISTER_TARGET_KIND("hexagon", kDLHexagon) .add_attr_option("mtriple") .add_attr_option("system-lib") .add_attr_option>("llvm-options") - .add_attr_option("host") .set_default_keys({"hexagon"}); TVM_REGISTER_TARGET_KIND("stackvm", kDLCPU) // line break - .add_attr_option("system-lib") - .add_attr_option("host"); + .add_attr_option("system-lib"); TVM_REGISTER_TARGET_KIND("ext_dev", kDLExtDev) // line break - .add_attr_option("system-lib") - .add_attr_option("host"); + .add_attr_option("system-lib"); TVM_REGISTER_TARGET_KIND("hybrid", kDLCPU) // line break - .add_attr_option("system-lib") - .add_attr_option("host"); + .add_attr_option("system-lib"); TVM_REGISTER_TARGET_KIND("composite", kDLCPU) - .add_attr_option("host") .add_attr_option>("devices"); /********** Registry **********/ diff --git a/tests/python/unittest/test_target_target.py b/tests/python/unittest/test_target_target.py index 11c52b7e0066..999553cb7106 100644 --- a/tests/python/unittest/test_target_target.py +++ b/tests/python/unittest/test_target_target.py @@ -193,6 +193,23 @@ def test_target_host_single_dict(): assert tgt.host.attrs["registers_per_block"] == 32768 +def test_target_host_single_string(): + tgt = tvm.target.Target("cuda --host llvm") + assert tgt.kind.name == "cuda" + assert tgt.host.kind.name == "llvm" + + +def test_target_host_single_string_with_tag(): + tgt = tvm.target.Target("cuda --host nvidia/jetson-nano") + assert tgt.kind.name == "cuda" + assert tgt.host.kind.name == "cuda" + assert tgt.host.attrs["arch"] == "sm_53" + assert tgt.host.attrs["shared_memory_per_block"] == 49152 + assert tgt.host.attrs["max_threads_per_block"] == 1024 + assert tgt.host.attrs["thread_warp_size"] == 32 + assert tgt.host.attrs["registers_per_block"] == 32768 + + if __name__ == "__main__": test_target_dispatch() test_target_string_parse() From 2f75e6c2bbb2232b182e19636c48a03cd0b77aeb Mon Sep 17 00:00:00 2001 From: Xiyou Zhou Date: Wed, 17 Feb 2021 15:56:11 -0800 Subject: [PATCH 08/10] Fix format issue --- src/target/target.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/target/target.cc b/src/target/target.cc index 5c97da3fbef1..b5ca4c38bbb9 100644 --- a/src/target/target.cc +++ b/src/target/target.cc @@ -375,8 +375,8 @@ Target::Target(const Map& config) { Target::Target(Target target, Target host) { ObjectPtr n = make_object(*target.get()); - CHECK(!n->host.defined()) << - "ValueError: Adding a host to a target whose host field has been defined"; + CHECK(!n->host.defined()) + << "ValueError: Adding a host to a target whose host field has been defined"; // add target host into host field n->host = std::move(host); data_ = std::move(n); @@ -476,7 +476,7 @@ void TargetInternal::ConstructorDispatcher(TVMArgs args, TVMRetValue* rv) { return; } LOG(FATAL) << "ValueError: Invalid number of arguments. Expect 1 or 2, but gets: " - << args.num_args; + << args.num_args; } ObjectPtr TargetInternal::FromString(const String& tag_or_config_or_target_str) { From 36713787883ec5f9907fafcbe6007e0d0268bcc7 Mon Sep 17 00:00:00 2001 From: Xiyou Zhou Date: Wed, 17 Feb 2021 16:06:43 -0800 Subject: [PATCH 09/10] Fix param description --- include/tvm/target/target.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/tvm/target/target.h b/include/tvm/target/target.h index add0547a0793..64bd251c0ded 100644 --- a/include/tvm/target/target.h +++ b/include/tvm/target/target.h @@ -141,15 +141,14 @@ class Target : public ObjectRef { * \return The target that is the current context. The target may not be defined if * allow_not_defined is true. */ - TVM_DLL explicit Target(Target target, Target host); + TVM_DLL static tvm::Target Current(bool allow_not_defined = true); /*! * \brief Construct a Target given target and host * \param target The Target typed object with host field undefined for target * \param host The Target typed object for target host * \return The Target with given target and host context information */ - TVM_DLL static tvm::Target Current(bool allow_not_defined = true); - + TVM_DLL explicit Target(Target target, Target host); TVM_DEFINE_OBJECT_REF_METHODS(Target, ObjectRef, TargetNode); private: From 71746c5373008409e5ed71d5862896f1d1c67a8c Mon Sep 17 00:00:00 2001 From: Xiyou Zhou Date: Thu, 18 Feb 2021 18:27:30 -0800 Subject: [PATCH 10/10] Add unit test for duplicate target hosts --- tests/python/unittest/test_target_target.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/python/unittest/test_target_target.py b/tests/python/unittest/test_target_target.py index 999553cb7106..7b998bef34a5 100644 --- a/tests/python/unittest/test_target_target.py +++ b/tests/python/unittest/test_target_target.py @@ -210,6 +210,15 @@ def test_target_host_single_string_with_tag(): assert tgt.host.attrs["registers_per_block"] == 32768 +def test_target_host_warning(): + """ + Confirm that constructing a target with invalid + attributes fails as expected. + """ + with pytest.raises(ValueError): + tgt = tvm.target.Target("cuda --host nvidia/jetson-nano", "llvm") + + if __name__ == "__main__": test_target_dispatch() test_target_string_parse()