Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion onnxruntime/core/providers/qnn/builder/qnn_model.cc
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,15 @@ Status QnnModel::SetupTensors(std::vector<QnnTensorInfo>& qnn_tensor_infos,
bool is_input) {
size_t tensor_count = tensor_wrappers.size();
ORT_RETURN_IF(0 == tensor_count, "Zero tensor size!");
qnn_tensor_infos.resize(tensor_count);
if (is_input) {
// Resize qnn_tensor_infos according to the number of graph inputs.
auto input_count = GetGraphInputCount();
ORT_RETURN_IF(input_count < tensor_count,
"The count of graph inputs should be at least the count of tensor_wrapper!");
qnn_tensor_infos.resize(input_count);
} else {
qnn_tensor_infos.resize(tensor_count);
}

for (auto& tensor_wrapper : tensor_wrappers) {
ORT_RETURN_IF(utils::QnnTensorHasDynamicShape(tensor_wrapper.GetQnnTensor()),
Expand All @@ -348,6 +356,18 @@ Status QnnModel::SetupTensors(std::vector<QnnTensorInfo>& qnn_tensor_infos,
qnn_tensor_info.tensor_byte_size = static_cast<uint32_t>(length);
qnn_tensor_info.ort_index = ort_index;
}
// The number of graph inputs and the number of tensor wrappers may not match.
// - For example, for ResizeNearestNeighbor op, Qnn only cares about the 1st input,
// so the rest of the inputs are not converted to tensor wrappers.
// - However, these remaining inputs still appear in the graph inputs, resulting in
// a discrepancy in the input quantities.
// If not all inputs are used, erase the empty allocations in qnn_tensor_infos.
if (is_input) {
qnn_tensor_infos.erase(std::remove_if(qnn_tensor_infos.begin(),
qnn_tensor_infos.end(),
[](QnnTensorInfo qnn_tensor_info) { return qnn_tensor_info.tensor_wrapper == nullptr; }),
qnn_tensor_infos.end());
}
return Status::OK();
}

Expand Down
5 changes: 5 additions & 0 deletions onnxruntime/core/providers/qnn/builder/qnn_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ class QnnModel {
return it->second;
}

// Return the number of graph inputs
size_t GetGraphInputCount() const {
return model_input_index_map_.size();
}

size_t GetOutputIndex(const std::string& name) const {
return GetInputOutputIndex(name, outputs_info_);
}
Expand Down
29 changes: 29 additions & 0 deletions onnxruntime/test/providers/qnn/qnn_basic_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <thread>

#include "core/graph/constants.h"
#include "core/graph/node_attr_utils.h"
#include "core/providers/cpu/cpu_provider_factory.h" // For OrtSessionOptionsAppendExecutionProvider_CPU
#if BUILD_QNN_EP_STATIC_LIB
#include "core/providers/qnn/qnn_allocator.h" // Used by QnnHTPBackendTests.UseHtpSharedMemoryAllocatorForInputs
Expand Down Expand Up @@ -1286,6 +1287,34 @@ TEST_F(QnnHTPBackendTests, AutoEp_PreferNpu) {
}
#endif // defined(WIN32) && !BUILD_QNN_EP_STATIC_LIB

// Test whether QNN EP can handle the case where the number of graph inputs and
// the number of tensor wrappers do not match.
// Take Resize op as an example.
// - Qnn only cares about the 1st input, so the rest of the inputs are not converted
// to tensor wrappers.
// - However, these remaining inputs still appear in the graph inputs,
// resulting in a discrepancy in the input quantities.
TEST_F(QnnHTPBackendTests, TestMismatchedGraphInputAndTensorWrapperCount) {
onnxruntime::ProviderOptions provider_options;
provider_options["backend_type"] = "htp";

auto input_defs = {TestInputDef<float>({1, 3, 10, 10}, false, -10.0f, 10.0f),
TestInputDef<float>({0}, false, {}),
TestInputDef<float>({4}, true, {1.0f, 1.0f, 2.0f, 2.0f})};
auto attrs = {utils::MakeAttribute("mode", "nearest"),
utils::MakeAttribute("coordinate_transformation_mode", "asymmetric"),
utils::MakeAttribute("nearest_mode", "floor")};
RunQnnModelTest(BuildOpTestCase<float>("Resize",
input_defs,
{},
attrs,
kOnnxDomain),
provider_options,
11,
ExpectedEPNodeAssignment::All,
0.008f);
}

#endif // defined(__aarch64__) || defined(_M_ARM64) || defined(__linux__)
#endif // !defined(ORT_MINIMAL_BUILD)

Expand Down
Loading