[Runtime][MatchShape] Type error: Cannot convert from type ' DLTensor* ' to ' ffi.Shape '
Summary
- This commit fixed error : "Type error: Cannot convert from type ' DLTensor* ' to ' ffi.Shape ' ".
- Error occurred at runtime when the first args of the MatchShape function (in runtime/vm/builtin.cc) is DLTensor*. If (auto opt_nd = args[0].as<Tensor>()) is false, args[0] (DLTensor*) will try convert to Shape.
Reproduce
RPC
- After over RPCWarppedFunc, Tensor will convert to DLTensor *
Cell In[3], line 189
186 remote_input = tvm.runtime.tensor(input_data, dev)
188 # Run inference on remote device
--> 189 output = vm["main"](remote_input)
191 # Extract result (handle both tuple and single tensor outputs)
192 if isinstance(output, tvm.ir.Array) and len(output) > 0:
File python/tvm_ffi/cython/function.pxi:904, in tvm_ffi.core.Function.__call__()
File ~/Programming/tvm/src/runtime/rpc/rpc_module.cc:141, in tvm::runtime::RPCWrappedFunc::operator()(tvm::ffi::PackedArgs, tvm::ffi::Any*) const()
139 }
140 auto set_return = [this, rv](ffi::PackedArgs args) { this->WrapRemoteReturnToValue(args, rv); };
--> 141 sess_->CallFunc(handle_, ffi::PackedArgs(packed_args.data(), packed_args.size()), set_return);
142 }
143
File ~/Programming/tvm/src/runtime/rpc/rpc_endpoint.cc:1116, in tvm::runtime::RPCClientSession::CallFunc(void*, tvm::ffi::PackedArgs, std::function<void (tvm::ffi::PackedArgs)> const&)()
1114 void CallFunc(PackedFuncHandle func, ffi::PackedArgs args,
1115 const FEncodeReturn& fencode_return) final {
-> 1116 endpoint_->CallFunc(func, args, fencode_return);
1117 }
1118
File ~/Programming/tvm/src/runtime/rpc/rpc_endpoint.cc:906, in tvm::runtime::RPCEndpoint::CallFunc(void*, tvm::ffi::PackedArgs, std::function<void (tvm::ffi::PackedArgs)>)()
904 handler_->SendPackedSeq(args.data(), args.size(), true);
905
--> 906 code = HandleUntilReturnEvent(true, encode_return);
907 ICHECK(code == RPCCode::kReturn) << "code=" << RPCCodeToString(code);
908 }
File ~/Programming/tvm/src/runtime/rpc/rpc_endpoint.cc:746, in tvm::runtime::RPCEndpoint::HandleUntilReturnEvent(bool, std::function<void (tvm::ffi::PackedArgs)>)()
744 }
745 }
--> 746 code = handler_->HandleNextEvent(client_mode, false, setreturn);
747 }
748 return code;
File ~/Programming/tvm/src/runtime/rpc/rpc_endpoint.cc:134, in tvm::runtime::RPCEndpoint::EventHandler::HandleNextEvent(bool, bool, std::function<void (tvm::ffi::PackedArgs)>)()
132 }
133 case kProcessPacket: {
--> 134 this->HandleProcessPacket(setreturn);
135 break;
136 }
File ~/Programming/tvm/src/runtime/rpc/rpc_endpoint.cc:409, in tvm::runtime::RPCEndpoint::EventHandler::HandleProcessPacket(std::function<void (tvm::ffi::PackedArgs)>)()
407 case RPCCode::kException:
408 case RPCCode::kReturn: {
--> 409 this->HandleReturn(code, setreturn);
410 break;
411 }
File ~/Programming/tvm/src/runtime/rpc/rpc_endpoint.cc:473, in tvm::runtime::RPCEndpoint::EventHandler::HandleReturn(tvm::runtime::RPCCode, std::function<void (tvm::ffi::PackedArgs)>)()
471 msg = "RPCError: Error caught from RPC call:\n" + msg;
472 }
--> 473 LOG(FATAL) << msg;
474 }
475
File ~/Programming/tvm/include/tvm/runtime/logging.h:321, in tvm::runtime::detail::LogFatal::~LogFatal()()
319 #endif
320 [[noreturn]] ~LogFatal() TVM_THROW_EXCEPTION {
--> 321 GetEntry().Finalize();
322 throw;
323 }
File ~/Programming/tvm/include/tvm/runtime/logging.h:337, in tvm::runtime::detail::LogFatal::Entry::Finalize()()
335 }
336 [[noreturn]] TVM_NO_INLINE dmlc::Error Finalize() TVM_THROW_EXCEPTION {
--> 337 InternalError error(file_, lineno_, stream_.str());
338 #if DMLC_LOG_BEFORE_THROW
339 std::cerr << error.what() << std::endl;
RPCError: Error caught from RPC call:
Cannot convert from type `DLTensor*` to `ffi.Shape`
C++
- Input is DLTensor *
std::cout << "--- TVM C++ TorchMLP Example ---" << std::endl;
int64_t shapes[] = {1, 1, 28, 28};
...
// Load binary data
std::vector<float> input_img = load_bin(argv[1], shapes[0] * shapes[1] * shapes[2] * shapes[3]);
// Create DLTensor for input
DLTensor* dl_tensor = new DLTensor();
dl_tensor->data = malloc(sizeof(float) * input_img.size());
dl_tensor->device = device;
dl_tensor->ndim = sizeof(shapes) / sizeof(shapes[0]);
dl_tensor->dtype = DLDataType{kDLFloat, 32, 1};
dl_tensor->shape = shapes;
dl_tensor->strides = nullptr;
dl_tensor->byte_offset = 0;
memcpy(dl_tensor->data, input_img.data(), sizeof(float) * input_img.size());
// Run the main function
tvm::ffi::Array<tvm::ffi::Tensor> ouput_temp = (*main)(dl_tensor).cast<tvm::ffi::Array<tvm::ffi::Tensor>>();
Resolved
- Instead of converting to Tensor, try_cast to DLTensor*, then create Shape
Summary of Changes
Hello @locnd182644, I'm Gemini Code Assist[^1]! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request addresses a critical runtime type conversion error within the MatchShape function, which previously led to failures when DLTensor* was passed as an argument. By enhancing the argument parsing to correctly interpret and process DLTensor* inputs, the change prevents crashes in RPC and C++ contexts. This improves the overall robustness and compatibility of the runtime system with various tensor representations, ensuring smoother execution of operations involving shape matching.
Highlights
- Fix
MatchShapeType Error: Resolved a runtime type error in theMatchShapefunction where it failed to correctly convert aDLTensor*argument toffi::Shape. This issue specifically occurred in scenarios involving RPC calls and direct C++ usage whereDLTensor*is passed as the first argument. - Improved Argument Handling: The
MatchShapefunction's argument parsing logic has been updated to first attempt atry_casttoDLTensor*. If successful, it now constructs theffi::Shapedirectly from theDLTensor*'sshapeandndimfields, ensuring proper handling of this tensor representation.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in pull request comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with :thumbsup: and :thumbsdown: on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
[^1]: Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.
@tvm-bot rerun