-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Target Pre-processing RFC #71
Conversation
Thanks @Mousius . Given these fields are pretty relevant to compiler configurations in traditional domain, it would be nice to also discuss prior approaches(e.g. where those fields normally sits in say LLVM) for posterity. This would also help us to make meaningful choices that aligns with existing terminologies. My quick read is that they seems to be aligned, but would be nice to double check. |
rfcs/0070-target-preprocessing.md
Outdated
## Architecture Pre-processing | ||
```c++ | ||
Target("c") | ||
.set_arch_preprocessor(MyArchPreprocessor) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If arch preprocessor is attached to Target
, then this precludes serializing targets into a string. Maybe we should just allow subclassing of targets?
Also, here the target is already created, so it should be something like apply_arch_preprocessor
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Embarrassingly, you have found a typo, this should be TVM_REGISTER_TARGET_KIND
, which should make it a lot clearer how this is meant to work 😸
When a Target
is parsed, the preprocessor will re-process the arguments and therefore re-production from a string should result new a new Target
with the pre-processed information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to make sure I understand, does this means that the only the first round trip of str -> Target -> str
is allowed to introduce changes? That is, round trips of Target -> str -> Target
will reproduce the original Target
, and round trips of str -> Target -> str
are idempotent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
str -> Target -> str
continues to function as it does today, where the AttrPreprocessor
may introduce changes in attributes, the KeysPreprocessor
would also behave this way. Theoretically, if the logic doesn't flip flop between values that should mean that the first change from str -> Target
creates all the values and you're correct that future transformations should be idempotent (I can't see a reason the logic would flip flop, but it is possible).
The ArchPreprocessor
does not hold this property as the arch
internal property is repopulated from attrs
on instantiation.
rfcs/0070-target-preprocessing.md
Outdated
```c++ | ||
class TargetKind { | ||
... | ||
FTVMArchPreprocessor arch_preprocessor; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's a part of TargetKind
, then you cannot customize it per specific architecture. For example, both x86-64 and aarch64 have the same kind: "llvm", but they will need different preprocessors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we'll end up with something similar to the example in clang
(https://github.com/llvm/llvm-project/blob/2f04e703bff3d9858f53225fa7c780b240c3e247/clang/lib/Driver/ToolChains/Clang.cpp#L331-L343) where the actual parser can take different routes dependent on more specific hints.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clang driver takes flags given by the user and translates them into specific "subtarget" configuration. There is a flag -target <triple>
, which roughly corresponds to a TargetMachine
, and then there are other details (implicit or explicit) that eventually create TargetSubtargetInfo
. That part of clang allows each target to specify the exact features, having already established what that target is. This is similar, for example, to how target kind "rocm" has attributes specific to the ROCm family, the key here being that we know we're dealing with ROCm, and not with any generic GPU.
The target kind "llvm", on the other hand, does correspond to any generic CPU, be it x86 or Arm. Flags specific to x86 may not be applicable to Arm, and vice versa. If we attach every arch preprocessor to kind "llvm", then whatever code executes them will have to know which preprocessor to apply, and currently there is no information that would aid with this selection.
This goes beyond the scope of this RFC, but my vote would be to eliminate "llvm" as a target kind, and replace it with specific kinds of CPUs. We could have target "host" that would correspond to the compilation host (and can be automatically translated to an appropriate specific CPU kind).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clang driver takes flags given by the user and translates them into specific "subtarget" configuration. There is a flag -target , which roughly corresponds to a TargetMachine, and then there are other details (implicit or explicit) that eventually create TargetSubtargetInfo.
Apologies, I oversimplified, you're right that Clang/LLVM has a few more data structures to describe this (including SubTarget
s) - in this RFC we're essentially using Map<String, ObjectRef>
as a replacement for most of the SubTarget
in the .arch
property. I can add further details to the Clang/LLVM Prior Art to reflect this 😸
The target kind "llvm", on the other hand, does correspond to any generic CPU, be it x86 or Arm. Flags specific to x86 may not be applicable to Arm, and vice versa. If we attach every arch preprocessor to kind "llvm", then whatever code executes them will have to know which preprocessor to apply, and currently there is no information that would aid with this selection.
Sorry, I'm not understanding so I'll provide an example 😸 , in the case of LLVM we'd attach a pre-processor which can inspect the attributes and do something similar to:
Map<String, ObjectRef> llvm_preprocessor(...attrs...) {
bool is_aarch64 = ...logic ...;
if (is_aarch64) {
return aarch64_preprocessor(...attrs...);
}
}
Therefore, whenever you instantiate a Target("llvm -march=aarch64-woof-woof-woof")
the preprocessor would give you a target.arch
Map
which would be pre-processed using the aarch64
processor, similar to the snippet I pasted from clang
with the switch
logic. This does mean we have to create a preprocessor for both the llvm
and c
Target
s to map mcpu
, march
, mtune
or mtriple
to the relevant logic path in the same way that LLVM suggests processing march
and mcpu
for SubTargetInfo
- this preprocessor would have the freedom to generate any eventual Map<String, ObjectRef>
for the specific details of a given architecture which is being targeted by the llvm
Target
of TVM.
This goes beyond the scope of this RFC, but my vote would be to eliminate "llvm" as a target kind, and replace it with specific kinds of CPUs. We could have target "host" that would correspond to the compilation host (and can be automatically translated to an appropriate specific CPU kind).
The Target
is definitely a difficult problem to unpick, so glad you agree it's out of scope 😸 , personally I would avoid magic Target
s such as "composite" and "host" in favour of better defining them - llvm
is maybe just a code generator for however we describe a CPU Target
? Potentially worth starting an RFC to get the discussion going and then discuss in the community meetup?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at your example: set_arch_preprocessor(MyArchPreprocessor)
, what arch would this apply to? If I need to add code to the llvm_preprocessor
above to recognize MyArch, and then call MyArchPreprocessor
, then there is no point in having the set_arch_preprocessor
in the first place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My initial thought was that MyArchPreprocessor
would be the CPU preprocessor which invokes other preprocessors when it decides they're appropriate. So you'd have:
Map<String, ObjectRef> AArch64PreProcessor(...attrs...) {
return ...things...;
}
Map<String, ObjectRef> CPUPreprocessor(...attrs...) {
bool is_aarch64 = ...logic ...;
if (is_aarch64) {
return AArch64PreProcessor(...attrs...);
}
}
TVM_REGISTER_TARGET_KIND("llvm", kDLCPU)
.set_arch_preprocessor(CPUPreprocessor);
Which then means when you invoke:
my_target = Target("llvm -mtriple=aarch64-woof-woof");
You can inspect it as:
my_target.arch.is_aarch64 // True
This then allows us to add multiple preprocessors to the llvm
Target
via the single CPU preprocessor entrypoint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be equivalent to adding arch
as an attribute, and setting it using the attribute preprocessor, wouldn't it? The difference is that with your proposal we don't access arch
as an attribute, but as a member.
Edit: Actually attrs
is a (public) member in Target
, it's just handled by helper functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my_target.arch.is_aarch64 // True
I think it would be my_target.arch["is_aarch64"]
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'll come out as my_target.arch.is_aarch64
due to using __getattr__
here to prettify the attributes:
https://github.com/apache/tvm-rfcs/pull/71/files#diff-c04c196e8069297e1fcfdd5a514a268b971943b265649eaa41edd8d47052d56aR142-R150
I think it's a good idea overall. I'm in favor of adding more internal flexibility to targets. |
Good idea @tqchen, one thing I've picked out from a second read of the LLVM approach is the term |
i'm supportive of this idea. i didn't want to derail this RFC by discussing @kparzysz-quic 's idea about the architecture of the llvm target here, but i think that would be a good follow-up discussion. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is generally ok. I suggest elaborating a bit more in the text of the RFC that the preprocessors apply to the target kind, and that for all architectures, the code specific to each architecture would need to be handled as a part of the common preprocessor. The use of names like MyArchPreprocessor
and MyKeysPreprocessor
suggests that there can be multiple specialized preprocessors. I'd replace them with CArchPreprocessor
and CKeysPreprocessor
, since they both show up in the c
target kind.
rfcs/0070-target-preprocessing.md
Outdated
These implementations can be stored under `src/target/preprocessors/<arch_identifier>.{cc.h}` to allow them to be composed together such as: | ||
|
||
* src/target/preprocessors/aarch64.cc | ||
* src/target/preprocessors/cpu.cc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd get rid of this section---it sounds like a recommendation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, do we not want to try and ensure these are consistently organised in the codebase?
Ideally I'd like to convey the ability to attach it to any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it overall, though I do have one potential concern: By making it easier to query the architecture compared to cross-architecture features, will developers more often use architecture-specific checks that unnecessarily limit TVM features to specific architectures?
Expanding, I can see three primary cases for querying the target:
- To select a schedule that has been hand-tuned for a specific architecture.
- To check if a schedule or optimization is capable of running on a specific target. (e.g. the schedule stays within the maximum number of registers)
- To select an implementation during lowering (e.g. only use a warp-level reduction if the target has a sufficient warp size)
Of these cases, the 1st case should compare against the architecture itself. The 2nd and 3rd cases should compare against specific features that are provided by that architecture, but may also be provided by other architectures.
While I don't think this is a major issue, I can see it becoming an issue over time if architecture checks are done for convenience instead of feature checks.
rfcs/0070-target-preprocessing.md
Outdated
@@ -0,0 +1,217 @@ | |||
- Feature Name: target-architecture-preprocessor | |||
- Start Date: 2022-04-04 | |||
- RFC PR: [apache/tvm-rfcs#0070](https://github.com/apache/tvm-rfcs/pull/0000) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: The RFC link doesn't point to the discussion PR. #70 points to the DeclBuffer RFC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😿
rfcs/0070-target-preprocessing.md
Outdated
using TargetKeys = Array<String>; | ||
|
||
using FTVMAttrPreprocessor = runtime::TypedPackedFunc<TargetAttrs(TargetAttrs)>; | ||
using FTVMArchPreprocessor = runtime::TypedPackedFunc<TargetArch(TargetAttrs)>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function signature wouldn't allow the TargetAttrs
to be modified as part of the FTVMArchPreprocessor
. If we're recognizing the architecture based on a specified "arch"
or "mcpu"
attribute, I think we should also modify the attributes to no longer contain the "arch"
or "mcpu"
attributes. Otherwise, we have the same information in two different locations, which allows discrepancies between the two representations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the breadth of TVM, I don't believe we can adequately clamp this to a specific set of input attributes?
Also, I was trying to not mutate the input attrs in favour of providing the new augmented object, so when you specify my_target = Target("c -mcpu=woofles")
you can reliably expect my_target.mcpu
to still provide the expected answer. Once processed, .arch
would give you a more detailed set of information about the combination of input attrs rather than attempting to replace them?
rfcs/0070-target-preprocessing.md
Outdated
## Architecture Pre-processing | ||
```c++ | ||
Target("c") | ||
.set_arch_preprocessor(MyArchPreprocessor) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to make sure I understand, does this means that the only the first round trip of str -> Target -> str
is allowed to introduce changes? That is, round trips of Target -> str -> Target
will reproduce the original Target
, and round trips of str -> Target -> str
are idempotent?
rfcs/0070-target-preprocessing.md
Outdated
```c++ | ||
Target my_target("c -mcpu=cortex-m4"); | ||
my_target->GetArch<Bool>("is_aarch64", false); // false | ||
my_target->GetArch<Bool>("has_dsp", false); // true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
What should determine whether a parameter is defined in
attrs
orarch
? -
How can a
Target
override the values used for an architecture?-
With the current design, it looks like this would be impossible. Because only the
FTVMKeysPreprocessor
takes thearch
as input, any two it looks like the answer is no. -
I think this would be a useful feature in order to selectively disable features for debugging and performance comparison. Alternatively, we'd get this same benefit if
GetAttr
is allowed to delegate toGetArch
for undefined values, and andGetArch
is only used internally.
-
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main distinction is the architecture features are inferred from the Target
attrs
, if we want users to pass it in then it would need to be in attrs
as you're correct there's no way of modifying it from a users point of view.
- I think this would be a useful feature in order to selectively disable features for debugging and performance comparison. Alternatively, we'd get this same benefit if
GetAttr
is allowed to delegate toGetArch
for undefined values, and andGetArch
is only used internally.
I referenced this a bit here:
https://github.com/apache/tvm-rfcs/pull/71/files#diff-c04c196e8069297e1fcfdd5a514a268b971943b265649eaa41edd8d47052d56aR174-R182
I'd rather keep Target
attrs
separated out from arch
so as not to confuse the Target
API by having too many things accessible as direct properties of it?
rfcs/0070-target-preprocessing.md
Outdated
|
||
using FTVMAttrPreprocessor = runtime::TypedPackedFunc<TargetAttrs(TargetAttrs)>; | ||
using FTVMArchPreprocessor = runtime::TypedPackedFunc<TargetArch(TargetAttrs)>; | ||
using FTVMKeysPreprocessor = runtime::TypedPackedFunc<TargetKeys(TargetAttrs, TargetKeys)>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the keys preprocessor is primarily used to define properties based on the architecture determined. It looks like this has significant overlap with the target tags. When should this be used instead of tags?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I don't see the overlap, taking the example of:
TVM_REGISTER_TARGET_TAG("raspberry-pi/4b-aarch64")
.set_config({{"kind", String("llvm")},
{"mtriple", String("aarch64-linux-gnu")},
{"mcpu", String("cortex-a72")},
{"mattr", Array<String>{"+neon"}},
{"num-cores", Integer(4)},
{"host", Map<String, ObjectRef>{{"kind", String("llvm")},
{"mtriple", String("aarch64-linux-gnu")},
{"mcpu", String("cortex-a72")},
{"mattr", Array<String>{"+neon"}},
{"num-cores", Integer(4)}}}});
These are pre-configured Target
s with various mtriple
, mcpu
and mattr
attributes already set - once pre-processed these can produce a set of architecture features for subsequent steps, such as replacing this check in the operator strategy:
Other tagged Target
s will likely have the same mattr
and mcpu
, thus rather than trying to hand craft the permutations each time, the pre-processor will 😸
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's also entirely possible that I'm misunderstanding. I had been both features as a way to define a bag of properties associated with some short key. For the tags the short key is the name of the tag, and for the new preprocessor the short key is the architecture name.
Unfortunately, this RFC neither improves nor worsens the situation you describe, I think the only way of really solving how the information is used is to limit the information visible to these functions. Also, Based on my previous re-review of LLVM, thanks to @tqchen, it might help to use |
I like that, and the renaming makes it clear which are boolean parameters and which are variable attributes. That would also be useful for cleaning up the Vulkan target, which right now has a large number of boolean attributes that would be better expressed as feature support. The renaming would also help with avoiding architecture-specific checks at the code review stage. Since the information defined by the architecture would be pulled over into |
Thanks @Mousius for drafing this RFC! First of all, I completely agree on the importance to handle To motivate discussion, I would love to provide more context on the system design, and then talk about some specific points I noticed in the current RFC, and finally propose some ideas inspired by this RFC. BackgroundDesign principles. Just wanted to share some of my design principles when developing TVM, the compiler I believe that aims to work across hardware models:
Current Special target attributes. Below are a few existing target attributes that serve special semantics, the design of which I don't fully agree with, but now are preserved as legacy:
Existing
Note that the number of attributes may grow if there is new hardware feature, but to the best of my knowledge, it could be less common that those hardware features may bloat, mainly because there is concrete cost to grow features on hardwares. Target tag system. Given the fact that existing hardware models are enumerable, the Target RFC proposes to use "tags" to allow easy creation of targets. For example, What on earth are DiscussionNaming choice. When implementing the Target RFC, I came up with the Where to dispatch target parsers. Currently, the preprocessor is dispatched solely based on Do we need multiple target parsers? My answer is no. If the parsers are maintained by different vendors separately on their own interest, then they could decide how to implement parsers for "keys", "arch", together, without conflicting with other contributors. Therefore, I would say it's already consistent with our principle A3 without having to develop multiple parsers. Function Signature for a target parser. Note that with the introduction of previous Target RFC, a target object is canonically represented by a JSON-like object. Therefore, the signature could be: using TargetJSON = Map<String, ObjectRef>;
using FTVMTargetParser = TypedPackedFunc<TargetJSON(TargetJSON)>; so that it's generic enough and could potentially be useful if vendors in the future want to hack around the Target object. To clarify the discussion here, I would propose that our parsing code path not go back to string again, i.e.:
Distinguishing Folder structure. According to principle A3, I would propose that different vendors may maintain their own TargetKind and parsers separately, for example, aarch64 could be maintained using:
|
Hi @junrushao1994, thanks for the elaborate reply 😸 I don't want to debate our personal principles but I appreciate you sharing them and will reference them where I can.
Yip, this fragmentation occurs due to a lack of a standardised mechanism for these groups to use, which the RFC aims to provide - I'm not sure why we consider that pollution given it should have a positive impact on all groups and aids in providing customisation through a well defined route established by all vendors, providing simplicity and customisation (A1, A2 and A3).
I believe this is still held given the crossover between hardware and code generators, for
There's definitely an existing amount of confusion in the
Which defines a system configuration that then uses a code generator The problem that I've faced trying to figure out how to implement this is that
I don't mind using one parser, I was just making it more granular and avoiding stepping on peoples toes with the existing pre-processor. Either design seems to fulfil your principle of customisability (A3), more granularly means you only have to implement a small piece of customisation where-as with the single parser it requires some thought as to how to cater for all attributes within a given
This requires developers to learn more than the bare minimum (A2), as users are required to learn the specifics of how to specify a
Based on LLVM, the
If we were to attach all of these directly to
I believe the proposed layout also conforms to A3 as it already details two different pre-processors, and you can easily imagine it extending:
The composition of OutcomesWill try and summarise the above into changes in the RFC which I can implement 😸 Single ParserI can re-word the RFC to use a single parser ( using TargetJSON = Map<String, ObjectRef>;
using FTVMTargetParser = TypedPackedFunc<TargetJSON(TargetJSON)>;
|
Thanks folks for discussions. I think they summarizes to the following points
|
@Mousius Thank you so much for your response! This makes lots of sense to me! Also, thanks for including my personal principles in the discussion! It's my personal principles which are completely okay to disagree with :-)
Sorry my words may lead to some potential miscommunication. As I mentioned in the very beginning, I completely agree with the idea of handling
Agreed. It is designed to be consistent with existing wisdom, i.e. LLVM/GCC mattr/mcpu/etc., so I believe it's not controversial.
Yes, I think your understanding is correct. Per Target RFC, this object represents host compiler info (C0), heterogeneous compilation settings (C1), compiler behavior control (C2), additional ISA/library (C4). Therefore, the tag system (C4) is introduced to reduce the cognitive overhead, because the end users can use a simple plain string tag
Right, in fact I share the same confusion with you with it comes to CUDA/Vulkan/etc., where (to best of my knowledge) there is no precedent of mcpu/mattr/mtriple/etc (except for LLVM NVPTX backend). Certainly, we should develop unified approach to address this confusion, which could possibly be the
Thanks for sharing your thoughts! Definitely. The issue of having multiple parsers is that the order of their application is less explicit, so I would be a little bit leaning towards a single one, while the implementation could share common helper functions.
Right. I agree.
Thank you for detailing the challenges! I'm convinced that
Sounds good to me! Overall, I think we are in broad agreement, and thanks for sharing all the context! |
great! so I think we just need some updates to the text of the RFC based on discusison, then we are good to merge. |
In the spirit of keeping this simple to review, the text of this RFC has been reformulated to cover the Hopefully this makes it simpler for everyone 😸 cc @kparzysz-quic @junrushao1994 @tqchen @areusch @Lunderberg |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks @Mousius just a couple clarifying questions about the text but I'm good with the overall approach
@areusch I replied to your comments, could you take a look and see if it makes more sense to you? Then if we're all happy I'll do a final update on the text 😸 |
@kparzysz-quic @junrushao1994 @tqchen @Lunderberg can you look at this one again? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
} | ||
|
||
TargetJSON CPUTargetParser(TargetJSON target) { | ||
if (IsAArch64Target(target)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless the details of the "kind" are listed in the JSON, there is no way of knowing what architecture the target refers to.
Actually, the target JSON only shows the name of the kind, so the target parser (if it operates on the JSON) won't see the details of the kind, unless they are included in the JSON. I think that expanding the contents of the target JSON to contain the kind specifics as well is critical for this feature to make sense. Please clarify of that's a part of the plan. |
Hi @kparzysz-quic, can you expand on what's missing here? According to https://discuss.tvm.apache.org/t/rfc-tvm-target-specification/6844, the Target JSON includes the |
Map<String, ObjectRef> TargetNode::Export() const {
Map<String, ObjectRef> result = {
{"kind", this->kind->name}, <------------
{"tag", this->tag},
{"keys", this->keys},
};
if (this->host.defined()) {
result.Set("host", this->GetHost().value_or(Target())->Export());
}
for (const auto& kv : attrs) {
result.Set(kv.first, kv.second);
}
return result;
} |
@kparzysz-quic, sorry, I'm still not understanding here - the name of the kind is enough to look it up in the kind registry and gather any kind-specific information. What further details are missing? |
I thought the attrs were stored in the kind, but they are in the target itself. Nevermind. |
This adds the `target_parser` as described in apache/tvm-rfcs#71, which parses an incoming `TargetJSON` and produces a new configuration for generating the final `Target` object from. Marks `set_attrs_preprocessor` as deprecated and errors if both `set_attrs_preprocessor` and `set_target_parser` exist together.
This adds the `target_parser` as described in apache/tvm-rfcs#71, which parses an incoming `TargetJSON` and produces a new configuration for generating the final `Target` object from. Marks `set_attrs_preprocessor` as deprecated and errors if both `set_attrs_preprocessor` and `set_target_parser` exist together.
@Mousius want to make the other suggested updates? then I'm good with this RFC |
This adds the `target_parser` as described in apache/tvm-rfcs#71, which parses an incoming `TargetJSON` and produces a new configuration for generating the final `Target` object from. Marks `set_attrs_preprocessor` as deprecated and errors if both `set_attrs_preprocessor` and `set_target_parser` exist together.
This adds the `target_parser` as described in apache/tvm-rfcs#71, which parses an incoming `TargetJSON` and produces a new configuration for generating the final `Target` object from. Marks `set_attrs_preprocessor` as deprecated and errors if both `set_attrs_preprocessor` and `set_target_parser` exist together.
No description provided.