-
Notifications
You must be signed in to change notification settings - Fork 58
[Discuss][IR] Relax PrimValue #274
Comments
Argument types used in Libtorch can be found here: https://github.com/pytorch/pytorch/tree/master/aten/src/ATen/native#registering-a-function-in-native_functionsyaml |
Thanks @YuchenJin for the proposal! I have a few comments on that.
|
I echo the thanks for writing up this proposal. As we discussed at the community meeting, I am a bit hesitant about including PrimValues as a separate type/value in the language because it would mean that there would be more than one way to represent the same value in Relax: We would have both rank-0 tensors (which represent scalars) and PrimValues. The choice of run-time representation (NDArray vs a TVM POD value) is a lower-level concern and perhaps should not require additional complexity in the front-end language, including in the type system. I would recommend using the NDArray representation wherever possible and converting in whichever operators do require PrimValues. We should profile the cost of such conversions--if the cost is small (imagining that we might have to do this multiple times in a model), I would say it's really not worth introducing the additional complexity into the front-end language. (The situation I would prefer to avoid is users getting mad that instantiating a constant results in the "wrong kind" of constant for whatever operator they're using, something which is likely to cause annoyance.) If we do introduce PrimValues as a separate value in the language, it might be worth having some policy for when we would prefer to use a PrimValue and when we would prefer to use a 0-rank tensor. @psrivas2 suggested one policy, of using tensors for all Relax-level operators and using PrimValues only for interacting with low-level libraries. That said, POD values can represent strings while NDArrays cannot, so perhaps one option might be to add a string constant node (or even allow strings to be passed as an argument to the I would also be hesitant to introduce a type that is not a subtype of |
Thanks everyone for the discussions at the community meeting today, and thanks @slyubomirsky and @psrivas2 for proposing alternative plans and summarizing the tradeoffs! Introducing a new type indeed needs careful consideration. One problem of using 0-rank tensors to represent POD values is that tensor is device-specific, while these POD values are always on host. Pytorch and other libraries make such distinction between host-only value and device-specific tensor. To reduce the complexity of writing passes, we can indeed restrict the Relax-level operators (for example comparison, addition, multiplications and other operators) to only take tensors, and use PrimValues only for interacting with low-level libraries as @psrivas2 suggested. The common case for our compiler is tensor arithmetics that needs to be optimized, and we want to reduce the complexity of such common case so optimization passes do not need to worry about more general cases; For PrimValue, having ability to be able to represent calls into libraries which can take PrimValue as arguments is sufficient and there is not a strong need to rewrite these parts during compilation. |
Follow-up question: Are PrimValues mutable? E.g., can a PackedFunc mutate them in place? I would assume (and hope) not. This would mean we have a distinction between what is passed by value and what is passed by reference, just like a lot of other languages (this might be useful for users). |
Thank you all for the great discussion! For @MasterJH5574,
It is unclear if they provide the general support for list, but they seem to support a list of integers. Take a look at
I believe this is what we need to figure out. So I would like to have some supports like tuple, but not sure this has to be For @slyubomirsky,
Based on my investigation so far, they seem to be invariants since main purpose is to pass the configuration values. For @YuchenJin ,
Do you assume that Libtorch fallback would be always running on the host device? |
Thanks for the discussions so far!
If we restrict the Relax-level operators to only take device-aware tensors, and restrict PrimValues to be only used for external function calls, PrimValues are not mutable: PrimValues are constant values that are passed as arguments to packed functions.
The Libtorch fallback functions can run on devices such as GPU, while the PrimValues are arguments on the host being passed to the kernel functions. These kernel functions are pass-by-value, and these arguments are copied by the host to a dedicated memory buffer on the device for example the constant memory on cuda gpu. |
For today's discussion for Open Dev meeting, I summarized our discussion so far. MotivationWe need a way to pass POD values (e.g., int, string, boolean) to Requirementssource: https://github.com/pytorch/pytorch/tree/master/aten/src/ATen/native#func
Options
|
Points of discussion from yesterday's Relax community's meeting:
Some possible directions:
We will continue discussions because we have not reached consensus on how to scope |
Personal opinion: If we aim to replace attributes with |
Thank you, @slyubomirsky for great summary! Based on our discussion yesterday, @YuchenJin and I could define the following action items:
Yesterday, I believe we reached consensus on A0 while leaving A1 and A2 as the future discussion topics. |
This is a draft proposal to show high-level ideas about supporting constant POD (plain-old-data) values (e.g., int, float, bool) in Relax IR.
Relax has first-class support of interacting with TVM FFI in the graph by calling into PackedFunc via
call_dps_packed
andcall_packed
. When integrating with third-party libraries such as LibTorch, third-party library functions may take constant arguments of POD data types. For example, ATen::unique takes optional boolean argumentssorted
andreturn_inverse
, and ATen::add takes optional integer argumentalpha
.So far we can represent such POD data types by wrapping them into a tvm attribute, but it needs special handling in the codegen and it’s hard to automatically generate such attributes.
To bridge the Relax IR with the runtime, we propose to introduce
PrimValue
to Relax to express primitive POD values in the IR.IR Representation
In this proposal, we introduce an expression
R.PrimValue
to Relax. APrimValue
is an IR construct that can represents POD values such as int, float, and boolean, and string.It can be implemented as a wrapper around
PrimExpr
, which can betir::IntImm
,tir::FloatImm
,tir::Bool
, andtir::StringImm
, .Type of PrimValue
We can reuse PrimType to represent POD values. Note PrimType is not a subtype of
relax.ObjectType
because at runtime, PrimValue does not map to a TVM runtime Object, while it maps toTVMPODValue_
.TVMScript example
The following code block demonstrates a simple Relax function with
call_dps_packed
andcall_packed
into libtorch functions:alpha=2
in the rhs of the first binding is parsed as aPrimValue
withtir::IntImm(2)
as the value.approximate
is a relax.Var ofPrimType
, and it can be passed intocall_dps_packed
as arguement.TVMRetValue
, which includeTVMPODValue_
andstd::string
.Other considerations:
Scope: Right now this design note restricts PrimValue to represent int, float, bool, or string and to be standalone. We can think of possible directions in the future:
tensor / int
as in pytorch and numpy.Tuple(int)
in the IR? One caveat is TVM container (e.g.,runtime.Tuple
) does not support POD data types today.The text was updated successfully, but these errors were encountered: