This is an automated email from the ASF dual-hosted git repository.

tlopex pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git


The following commit(s) were added to refs/heads/main by this push:
     new ec0fed0f0d [Runtime][MatchShape] Type error: Cannot convert from type 
' DLTensor* ' to ' ffi.Shape ' (#18546)
ec0fed0f0d is described below

commit ec0fed0f0d76592aa7c48130d1eef5efa21940e3
Author: Nguyen Duy Loc <[email protected]>
AuthorDate: Wed Dec 24 14:49:54 2025 +0700

    [Runtime][MatchShape] Type error: Cannot convert from type ' DLTensor* ' to 
' ffi.Shape ' (#18546)
    
    # 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 *
    <img width="887" height="975" alt="RPCWrappedFunc Editpng"
    
src="https://github.com/user-attachments/assets/e80d1798-49ab-4d33-b9c5-2bb85bd53b87";
    />
    
    ```
    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>>();
    
    ```
    <img width="615" height="147" alt="cpp"
    
src="https://github.com/user-attachments/assets/abbcd829-9aec-48f0-ac5d-804f7e9cbff0";
    />
    
    # Resolved
    - Instead of converting to Tensor, try_cast to DLTensor*, then create
    Shape
---
 src/runtime/vm/builtin.cc | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/runtime/vm/builtin.cc b/src/runtime/vm/builtin.cc
index 1bd3084c21..dce687b436 100644
--- a/src/runtime/vm/builtin.cc
+++ b/src/runtime/vm/builtin.cc
@@ -122,10 +122,13 @@ TVM_FFI_STATIC_INIT_BLOCK() {
  * \sa MatchShapeCode
  */
 void MatchShape(ffi::PackedArgs args, ffi::Any* rv) {
-  // input shape the first argument can take in tensor or shape.
+  // input shape the first argument can take in tensor, DLTensor* or shape.
   ffi::Shape input_shape;
-  if (auto opt_nd = args[0].as<Tensor>()) {
-    input_shape = opt_nd.value().Shape();
+  if (auto opt_tensor = args[0].as<Tensor>()) {
+    input_shape = opt_tensor.value().Shape();
+  } else if (auto opt_dltensor = args[0].try_cast<DLTensor*>()) {
+    DLTensor* ptr = opt_dltensor.value();
+    input_shape = ffi::Shape(ptr->shape, ptr->shape + ptr->ndim);
   } else {
     input_shape = args[0].cast<ffi::Shape>();
   }

Reply via email to