-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
[FFI] Allow IntImm arguments to PackedFunc with int parameter #15983
Conversation
TVM containers, such as tvm::runtime::Array, require the contained objects to inherit from `ObjectRef`. As a result, the wrapper types `IntImm`, `FloatImm`, and `StringImm` are often used to allow native types in the TVM containers. Conversions into these wrapper type may be required when using a container, and may be performed automatically when passing an object across the FFI. By also providing conversion to an unwrapped type, these automatic conversions are transparent become transparent to users. The trait can be specialized to add type specific conversion logic from the TVMArgvalue and TVMRetValue.
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 @Lunderberg! Looks good, just some comments.
include/tvm/runtime/packed_func.h
Outdated
} else if (auto opt = ThroughObjectRef<double>()) { | ||
return opt.value(); | ||
} else if (auto opt = ThroughObjectRef<int64_t>()) { | ||
return opt.value(); |
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.
Shouldn't there be static_cast<double>
, as in line 588?
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.
Good catch. It isn't strictly necessary in either case, due to C++'s implicit conversion of numeric types, but would be good to call attention to it. Updated to use a static_cast<double>
here.
* ObjectRef to primitive types. | ||
* | ||
* TVM containers, such as tvm::runtime::Array, require the contained | ||
* objects to inherit from ObjectRef. As a result, the wrapper types |
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.
Trailing whitespace, also in lines 550, 552.
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'm not seeing the trailing whitespace in the commit, either using git show --word-diff-regex="[ ]+|[^ ]+"
, setting my editor to show whitespace, or in the github diff.
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.
Sorry, I used the wrong definition, there is a double space before "As"
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.
Ah, I see. This is intentional, but is more of a stylistic difference than anything else. Traditionally, (accidental diversion into typography) a space after a sentence would use an em space (the same with as a capital M) after a sentence, wider than the spacing between words. This isn't possible in monospaced fonts, so typewriters would emulate the em space by using two spaces. Exactly which is better has since become the topic of a great many flame wars.
I was curious, and it looks like double-spacing after a sentence is about twice as common as single-spacing in the TVM repo, with the Apache copyright header being the most prominent example.
# Count the number of sentences followed by one space
$ find . \
\( -path ./3rdparty -o -path "./build*" \) -prune -o \
\( -name "*.cc" -o -name "*.h" \) \
-exec grep '[A-Za-z]\{2\}\. [A-Za-z]' {} /dev/null \; \
| wc --lines
3958
# Count the number of sentences followed by two spaces
$ find . \
\( -path ./3rdparty -o -path "./build*" \) -prune -o \
\( -name "*.cc" -o -name "*.h" \) \
-exec grep '[A-Za-z]\{2\}\. [A-Za-z]' {} /dev/null \; \
| wc --lines
7666
TypedPackedFunc<void(double)> typed_func = [](double x) {}; | ||
PackedFunc func = typed_func; | ||
|
||
// Argument may be provided as a floating point. If provided as an |
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.
Trailing whitespace.
Given the implementation complexity i feel it would be helpful to not support this implicit behavior for now. This is because IntImm are used in other purposes(e.g. that comes with dtype). This may start to make sense once we start to introduce a BoxInt that do not contain the dtype field and simply serve as a dtype function. I assume downstream packedfunc will still be able to handle the function correctly by either expecting the object or non-object variant |
This arose when writing unit tests for access of a relax tuple. I expected the following unit test to pass on import tvm.testing
from tvm.script import relax as R
exec_mode = tvm.testing.parameter("bytecode", "compiled")
def test_vm_tuple_get_item(exec_mode):
@R.function(private=True)
def func(arg: R.Tuple([R.Prim("int64"), R.Prim("float32")])):
return arg[0]
mod = tvm.IRModule({"main": func})
target = tvm.target.Target("llvm", host="llvm")
ex = tvm.relax.build(mod, target, exec_mode=exec_mode)
vm = tvm.relax.VirtualMachine(ex, tvm.cpu())
res = vm["main"]((17, 42.5))
assert res == 17 The error occurs with the following steps:
Any of these steps could be broken in order to avoid the error. Fundamentally, the error occurs because we apply an automatic conversion (
Can you explain what you mean here? This doesn't seem any more complex than the argument handling that we already do for FFI compatibility purposes. |
I understand the error scenario you described, and also agree this is an issue when we start to involve tuple of prim values. I just would like to bring up the point about path to support these cases. One current issue is that IntImm and FloatImm are compile time construct that are not defined as partof the runtime (because they are coupled as Expr). As a result, generalizing IntImm/FloatImm implementation won't allow us to support the case where only tvm_runtime is available, which is a common case to support. A better approach would be to enable boxed Given tuple of two prim values are less commonly used and we only recently supported the prim values. I think it is better for us to not support the case for now, so we can later go for a longer term solution that separates out dedicated runtime boxed values, in which case automatic conversion would makes sense and there won't be limitations that it won't work in a runtime onlys etting. In the meantime, we first report error for cases that involves tuple of prim values, and expand our scope of support once the boxed version of values land(which enables generic solution for runtime only cases as well) |
I like the idea of having the separate runtime-only types, as distinct from the compile-time representations. I was concerned that that would be a larger impact change, but I agree with that as the long-term approach. For now, closing this PR to avoid any premature merging.
For my understanding, I thought that |
This PR has been superseded by #16183, which implements boxed primitives that can be used as part of |
TVM containers, such as tvm::runtime::Array, require the contained objects to inherit from
ObjectRef
. As a result, the wrapper typesIntImm
,FloatImm
, andStringImm
are often used to allow native types in the TVM containers. Conversions into these wrapper type may be required when using a container, and may be performed automatically when passing an object across the FFI. By also providing conversion to an unwrapped type, these automatic conversions are transparent become transparent to users.