Skip to content

Commit f3251de

Browse files
authored
[QNN-EP] Enable translation of FP16 Expand op (#26031)
### Description The Expand op builder for QNN did not handle FP16 data. Enabling it in this change and adding Expand tests for the GPU backend.
1 parent d9f3598 commit f3251de

File tree

2 files changed

+123
-44
lines changed

2 files changed

+123
-44
lines changed

onnxruntime/core/providers/qnn/builder/opbuilder/expand_op_builder.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ Status ExpandOpBuilder::ProcessInputs(QnnModelWrapper& qnn_model_wrapper,
114114
FillShapeInputData(shape_data, shape_size, static_cast<float>(1.0));
115115
break;
116116
}
117+
case QNN_DATATYPE_FLOAT_16: {
118+
FillShapeInputData(shape_data, shape_size, static_cast<MLFloat16>(1.0f));
119+
break;
120+
}
117121
case QNN_DATATYPE_INT_64: {
118122
// QNN-EP doesn't support INT64 shape input.
119123
qnn_data_type = QNN_DATATYPE_INT_32;

onnxruntime/test/providers/qnn/reshape_expand_op_test.cc

Lines changed: 119 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,19 @@
1414
namespace onnxruntime {
1515
namespace test {
1616

17-
// Runs a model with a Reshape/Expand operator on the QNN CPU backend. Checks the graph node assignment
17+
// Runs a model with a Reshape/Expand operator on the QNN CPU or GPU backends. Checks the graph node assignment
1818
// and that inference outputs for QNN EP and CPU EP match.
1919
template <typename DataType>
20-
static void RunReshapeExpandTestOnCPU(const std::string& op_type,
21-
const TestInputDef<DataType>& input_def,
22-
const TestInputDef<int64_t>& shape_def,
23-
const std::vector<ONNX_NAMESPACE::AttributeProto>& attrs,
24-
ExpectedEPNodeAssignment expected_ep_assignment,
25-
int opset = 19) {
20+
static void RunReshapeExpandTest(const std::string& op_type,
21+
const TestInputDef<DataType>& input_def,
22+
const TestInputDef<int64_t>& shape_def,
23+
const std::vector<ONNX_NAMESPACE::AttributeProto>& attrs,
24+
ExpectedEPNodeAssignment expected_ep_assignment,
25+
const std::string& backend_name = "cpu",
26+
int opset = 19) {
2627
ProviderOptions provider_options;
2728

28-
provider_options["backend_type"] = "cpu";
29+
provider_options["backend_type"] = backend_name;
2930
provider_options["offload_graph_io_quantization"] = "0";
3031

3132
RunQnnModelTest(BuildOpTestCase<DataType, int64_t>(op_type, {input_def}, {shape_def}, attrs),
@@ -40,68 +41,142 @@ static void RunReshapeExpandTestOnCPU(const std::string& op_type,
4041

4142
// Test that Reshape with a dynamic shape input is not supported by QNN EP.
4243
TEST_F(QnnCPUBackendTests, Reshape_DynamicShape_Unsupported) {
43-
RunReshapeExpandTestOnCPU("Reshape",
44-
TestInputDef<float>({1, 3, 4, 4}, false, -10.0f, 10.0f),
45-
TestInputDef<int64_t>({2}, false /* is_initializer */, {1, 48}),
46-
{}, // Attributes
47-
ExpectedEPNodeAssignment::None, // Should not be assigned to QNN EP.
48-
19); // Opset
44+
RunReshapeExpandTest("Reshape",
45+
TestInputDef<float>({1, 3, 4, 4}, false, -10.0f, 10.0f),
46+
TestInputDef<int64_t>({2}, false /* is_initializer */, {1, 48}),
47+
{}, // Attributes
48+
ExpectedEPNodeAssignment::None, // Should not be assigned to QNN EP.
49+
"cpu", // Backend
50+
19); // Opset
4951
}
5052

5153
// Test that Reshape with an enabled 'allowzero' attribute is not supported by QNN EP.
5254
TEST_F(QnnCPUBackendTests, Reshape_AllowZeroAttr_Unsupported) {
53-
RunReshapeExpandTestOnCPU("Reshape", TestInputDef<float>({1, 3, 4, 4}, false, -10.0f, 10.0f),
54-
TestInputDef<int64_t>({2}, true, {1, 48}),
55-
{utils::MakeAttribute("allowzero", static_cast<int64_t>(1))},
56-
ExpectedEPNodeAssignment::None, // Should not be assigned to QNN EP.
57-
19); // Opset
55+
RunReshapeExpandTest("Reshape", TestInputDef<float>({1, 3, 4, 4}, false, -10.0f, 10.0f),
56+
TestInputDef<int64_t>({2}, true, {1, 48}),
57+
{utils::MakeAttribute("allowzero", static_cast<int64_t>(1))},
58+
ExpectedEPNodeAssignment::None, // Should not be assigned to QNN EP.
59+
"cpu", // Backend
60+
19); // Opset
5861
}
5962

6063
// Test Reshape of rank 4 -> rank 2.
6164
TEST_F(QnnCPUBackendTests, Reshape_4D_f32) {
62-
RunReshapeExpandTestOnCPU("Reshape", TestInputDef<float>({1, 3, 4, 4}, false, GetFloatDataInRange(-10.0f, 10.0f, 48)),
63-
TestInputDef<int64_t>({2}, true, {1, 48}),
64-
{}, // Attributes
65-
ExpectedEPNodeAssignment::All,
66-
19); // Opset
65+
RunReshapeExpandTest("Reshape", TestInputDef<float>({1, 3, 4, 4}, false, GetFloatDataInRange(-10.0f, 10.0f, 48)),
66+
TestInputDef<int64_t>({2}, true, {1, 48}),
67+
{}, // Attributes
68+
ExpectedEPNodeAssignment::All,
69+
"cpu", // Backend
70+
19); // Opset
6771
}
6872

6973
// Test Expand with non-initializer shape input, not supported.
7074
TEST_F(QnnCPUBackendTests, Expand_NonIniShape) {
71-
RunReshapeExpandTestOnCPU("Expand", TestInputDef<float>({1}, false, {1.0f}),
72-
TestInputDef<int64_t>({2}, false, {2, 2}),
73-
{}, // Attributes
74-
ExpectedEPNodeAssignment::None,
75-
19); // Opset
75+
RunReshapeExpandTest("Expand", TestInputDef<float>({1}, false, {1.0f}),
76+
TestInputDef<int64_t>({2}, false, {2, 2}),
77+
{}, // Attributes
78+
ExpectedEPNodeAssignment::None,
79+
"cpu", // Backend
80+
19); // Opset
7681
}
7782

7883
// Test Expand with initializer shape input.
7984
TEST_F(QnnCPUBackendTests, Expand_IniShape) {
80-
RunReshapeExpandTestOnCPU("Expand", TestInputDef<float>({1}, false, {1.0f}),
81-
TestInputDef<int64_t>({2}, true, {2, 3}),
82-
{}, // Attributes
83-
ExpectedEPNodeAssignment::All,
84-
19); // Opset
85+
RunReshapeExpandTest("Expand", TestInputDef<float>({1}, false, {1.0f}),
86+
TestInputDef<int64_t>({2}, true, {2, 3}),
87+
{}, // Attributes
88+
ExpectedEPNodeAssignment::All,
89+
"cpu", // Backend
90+
19); // Opset
8591
}
8692

8793
// Test Expand with initializer shape input.
8894
TEST_F(QnnCPUBackendTests, Expand_Uint32) {
89-
RunReshapeExpandTestOnCPU("Expand", TestInputDef<uint32_t>({1}, false, {1}),
90-
TestInputDef<int64_t>({2}, true, {2, 3}),
91-
{}, // Attributes
92-
ExpectedEPNodeAssignment::All,
93-
19); // Opset
95+
RunReshapeExpandTest("Expand", TestInputDef<uint32_t>({1}, false, {1}),
96+
TestInputDef<int64_t>({2}, true, {2, 3}),
97+
{}, // Attributes
98+
ExpectedEPNodeAssignment::All,
99+
"cpu", // Backend
100+
19); // Opset
94101
}
95102

96103
// Test Expand with 6D output.
97104
TEST_F(QnnCPUBackendTests, Expand_6D) {
98-
RunReshapeExpandTestOnCPU("Expand", TestInputDef<float>({3}, false, {1.0f, 2.0f, 3.0f}),
99-
TestInputDef<int64_t>({6}, true, {1, 2, 3, 4, 5, 3}),
100-
{}, // Attributes
101-
ExpectedEPNodeAssignment::All,
102-
19); // Opset
105+
RunReshapeExpandTest("Expand", TestInputDef<float>({3}, false, {1.0f, 2.0f, 3.0f}),
106+
TestInputDef<int64_t>({6}, true, {1, 2, 3, 4, 5, 3}),
107+
{}, // Attributes
108+
ExpectedEPNodeAssignment::All,
109+
"cpu", // Backend
110+
19); // Opset
111+
}
112+
113+
#if defined(_M_ARM64)
114+
//
115+
// GPU tests:
116+
//
117+
118+
// Test Reshape of rank 4 -> rank 2.
119+
TEST_F(QnnGPUBackendTests, Reshape_4D_f32) {
120+
RunReshapeExpandTest("Reshape", TestInputDef<float>({1, 3, 4, 4}, false, GetFloatDataInRange(-10.0f, 10.0f, 48)),
121+
TestInputDef<int64_t>({2}, true, {1, 48}),
122+
{}, // Attributes
123+
ExpectedEPNodeAssignment::All,
124+
"gpu", // Backend
125+
19); // Opset
126+
}
127+
128+
// Test Expand with initializer shape input.
129+
TEST_F(QnnGPUBackendTests, Expand_IniShape) {
130+
RunReshapeExpandTest("Expand", TestInputDef<float>({1}, false, {1.0f}),
131+
TestInputDef<int64_t>({2}, true, {2, 3}),
132+
{}, // Attributes
133+
ExpectedEPNodeAssignment::All,
134+
"gpu", // Backend
135+
19); // Opset
136+
}
137+
138+
// Test Expand with FP16 data
139+
TEST_F(QnnGPUBackendTests, Expand_IniShape_Float16) {
140+
RunReshapeExpandTest("Expand", TestInputDef<MLFloat16>({1}, false, {MLFloat16(1.0f)}),
141+
TestInputDef<int64_t>({2}, true, {2, 3}),
142+
{}, // Attributes
143+
ExpectedEPNodeAssignment::All,
144+
"gpu", // Backend
145+
19); // Opset
146+
}
147+
148+
// Test Expand with 6D output.
149+
TEST_F(QnnGPUBackendTests, Expand_6D) {
150+
RunReshapeExpandTest("Expand", TestInputDef<float>({3}, false, {1.0f, 2.0f, 3.0f}),
151+
TestInputDef<int64_t>({6}, true, {1, 2, 3, 4, 5, 3}),
152+
{}, // Attributes
153+
ExpectedEPNodeAssignment::All,
154+
"gpu", // Backend
155+
19); // Opset
156+
}
157+
158+
// Test Expand with 6D output with FP16 data.
159+
TEST_F(QnnGPUBackendTests, Expand_6D_Float16) {
160+
RunReshapeExpandTest("Expand", TestInputDef<MLFloat16>({3}, false, {MLFloat16(1.0f), MLFloat16(2.0f), MLFloat16(3.0f)}),
161+
TestInputDef<int64_t>({6}, true, {1, 2, 3, 4, 5, 3}),
162+
{}, // Attributes
163+
ExpectedEPNodeAssignment::All,
164+
"gpu", // Backend
165+
19); // Opset
103166
}
104167

168+
// Test Expand with 4D output with FP16 data.
169+
TEST_F(QnnGPUBackendTests, Expand_4D_Float16) {
170+
RunReshapeExpandTest("Expand", TestInputDef<MLFloat16>({1, 2, 1, 1}, false, {MLFloat16(1.0f), MLFloat16(2.0f)}),
171+
TestInputDef<int64_t>({4}, true, {1, 2, 128, 128}),
172+
{}, // Attributes
173+
ExpectedEPNodeAssignment::All,
174+
"gpu", // Backend
175+
19); // Opset
176+
}
177+
178+
#endif // defined(_M_ARM64) GPU tests
179+
105180
#if defined(__aarch64__) || defined(_M_ARM64) || defined(__linux__)
106181
//
107182
// HTP tests:

0 commit comments

Comments
 (0)