@@ -41,15 +41,19 @@ static void RunTopKTestOnCPU(const TestInputDef<DataType>& input_def,
4141 const TestInputDef<int64_t >& k_def,
4242 const std::vector<ONNX_NAMESPACE::AttributeProto>& attrs,
4343 ExpectedEPNodeAssignment expected_ep_assignment,
44- int opset = 19 ) {
44+ int opset = 19 ,
45+ bool verify_outputs = true ) {
4546 ProviderOptions provider_options;
4647
4748 provider_options[" backend_type" ] = " cpu" ;
4849
4950 RunQnnModelTest (BuildTopKTestCase<DataType>(input_def, k_def, attrs),
5051 provider_options,
5152 opset,
52- expected_ep_assignment);
53+ expected_ep_assignment,
54+ /* fp32_abs_err*/ 1e-5f ,
55+ /* log_severity*/ logging::Severity::kERROR ,
56+ /* verify_outputs*/ verify_outputs);
5357}
5458
5559//
@@ -72,12 +76,13 @@ TEST_F(QnnCPUBackendTests, TopK_NonLastAxis) {
7276 ExpectedEPNodeAssignment::All);
7377}
7478
75- // Test that TopK that returns the top k minimum values is not supported by QNN EP .
76- TEST_F (QnnCPUBackendTests, TopK_MinValues_Unsupported ) {
79+ // Test that TopK with an axis attribute that is not the last dimension. Set largest to 0 .
80+ TEST_F (QnnCPUBackendTests, TopK_NonLastAxis_Largest_0 ) {
7781 RunTopKTestOnCPU<float >(TestInputDef<float >({1 , 3 , 4 , 4 }, false , GetFloatDataInRange (-10 .0f , 10 .0f , 48 )),
7882 TestInputDef<int64_t >({1 }, true /* is_initializer */ , {2 }),
79- {utils::MakeAttribute (" largest" , static_cast <int64_t >(0 ))},
80- ExpectedEPNodeAssignment::None); // Should not be assigned to QNN EP.
83+ {utils::MakeAttribute (" axis" , static_cast <int64_t >(1 )),
84+ utils::MakeAttribute (" largest" , static_cast <int64_t >(0 ))},
85+ ExpectedEPNodeAssignment::All);
8186}
8287
8388// Test TopK on CPU backend: top 2 largest floats from last axis
@@ -88,6 +93,25 @@ TEST_F(QnnCPUBackendTests, TopK_LargestFloats_LastAxis) {
8893 ExpectedEPNodeAssignment::All);
8994}
9095
96+ // Test TopK on CPU backend: top 2 largest floats from last axis. Largest to 0.
97+ TEST_F (QnnCPUBackendTests, TopK_LargestFloats_LastAxis_Largest_0) {
98+ RunTopKTestOnCPU<float >(TestInputDef<float >({1 , 3 , 4 , 4 }, false , GetFloatDataInRange (-10 .0f , 10 .0f , 48 )),
99+ TestInputDef<int64_t >({1 }, true /* is_initializer */ , {2 }),
100+ {utils::MakeAttribute (" largest" , static_cast <int64_t >(0 ))}, // Attributes
101+ ExpectedEPNodeAssignment::All);
102+ }
103+
104+ // Test TopK on CPU backend: top 2 largest floats from last axis. Set largest to 0. Set sorted to false.
105+ TEST_F (QnnCPUBackendTests, TopK_LargestFloats_LastAxis_Largest_0_Sorted) {
106+ RunTopKTestOnCPU<float >(TestInputDef<float >({1 , 3 , 4 , 4 }, false , GetFloatDataInRange (-10 .0f , 10 .0f , 48 )),
107+ TestInputDef<int64_t >({1 }, true /* is_initializer */ , {2 }),
108+ {utils::MakeAttribute (" largest" , static_cast <int64_t >(0 )),
109+ utils::MakeAttribute (" sorted" , static_cast <int64_t >(0 ))}, // Attributes
110+ ExpectedEPNodeAssignment::All,
111+ /* opset*/ 19 ,
112+ /* verify_outputs*/ false ); // Disable verify output. Unsorted doesn't guarantee output sequence
113+ }
114+
91115// Test TopK on CPU backend: top 2 largest int32s from last axis
92116TEST_F (QnnCPUBackendTests, TopK_LargestInt32s_LastAxis) {
93117 std::vector<int32_t > input_data = {-6 , -5 , -4 , -3 , -2 , 0 , 1 , 2 , 3 , 4 , 5 , 6 };
@@ -97,6 +121,27 @@ TEST_F(QnnCPUBackendTests, TopK_LargestInt32s_LastAxis) {
97121 ExpectedEPNodeAssignment::All);
98122}
99123
124+ // Test TopK on CPU backend: top 2 largest int32s from last axis. Set largest to 0.
125+ TEST_F (QnnCPUBackendTests, TopK_LargestInt32s_LastAxis_Largest_0) {
126+ std::vector<int32_t > input_data = {-6 , -5 , -4 , -3 , -2 , 0 , 1 , 2 , 3 , 4 , 5 , 6 };
127+ RunTopKTestOnCPU<int32_t >(TestInputDef<int32_t >({1 , 2 , 2 , 3 }, false , input_data),
128+ TestInputDef<int64_t >({1 }, true /* is_initializer */ , {2 }),
129+ {utils::MakeAttribute (" largest" , static_cast <int64_t >(0 ))}, // Attributes
130+ ExpectedEPNodeAssignment::All);
131+ }
132+
133+ // Test TopK on CPU backend: top 2 largest int32s from last axis. Set largest to 0. Set sorted to false.
134+ TEST_F (QnnCPUBackendTests, TopK_LargestInt32s_LastAxis_Largest_0_Sorted) {
135+ std::vector<int32_t > input_data = {-6 , -5 , -4 , -3 , -2 , 0 , 1 , 2 , 3 , 4 , 5 , 6 };
136+ RunTopKTestOnCPU<int32_t >(TestInputDef<int32_t >({1 , 2 , 2 , 3 }, false , input_data),
137+ TestInputDef<int64_t >({1 }, true /* is_initializer */ , {2 }),
138+ {utils::MakeAttribute (" largest" , static_cast <int64_t >(0 )),
139+ utils::MakeAttribute (" sorted" , static_cast <int64_t >(0 ))}, // Attributes
140+ ExpectedEPNodeAssignment::All,
141+ /* opset*/ 19 ,
142+ /* verify_outputs*/ false ); // Disable verify output. Unsorted doesn't guarantee output sequence
143+ }
144+
100145#if defined(__aarch64__) || defined(_M_ARM64) || defined(__linux__)
101146//
102147// HTP tests:
@@ -166,6 +211,14 @@ TEST_F(QnnHTPBackendTests, TopK_LargestFloats_U8_LastAxis) {
166211 ExpectedEPNodeAssignment::All);
167212}
168213
214+ // Test 8-bit QDQ TopK on HTP backend: top 2 largest floats from last axis. Set largest to 0.
215+ TEST_F (QnnHTPBackendTests, TopK_LargestFloats_U8_LastAxis_Largest_0) {
216+ RunQDQTopKTestOnHTP<uint8_t >(TestInputDef<float >({1 , 3 , 4 , 4 }, false , GetFloatDataInRange (-10 .0f , 10 .0f , 48 )),
217+ TestInputDef<int64_t >({1 }, true /* is_initializer */ , {2 }),
218+ {utils::MakeAttribute (" largest" , static_cast <int64_t >(0 ))}, // Attributes
219+ ExpectedEPNodeAssignment::All);
220+ }
221+
169222// Test 8-bit QDQ TopK on HTP backend: non-last axis
170223TEST_F (QnnHTPBackendTests, TopK_U8_NonLastAxis) {
171224 RunQDQTopKTestOnHTP<uint8_t >(TestInputDef<float >({1 , 3 , 4 , 4 }, false , GetFloatDataInRange (-10 .0f , 10 .0f , 48 )),
@@ -174,6 +227,15 @@ TEST_F(QnnHTPBackendTests, TopK_U8_NonLastAxis) {
174227 ExpectedEPNodeAssignment::All);
175228}
176229
230+ // Test 8-bit QDQ TopK on HTP backend: non-last axis. Set largest to 0.
231+ TEST_F (QnnHTPBackendTests, TopK_U8_NonLastAxis_Largest_0) {
232+ RunQDQTopKTestOnHTP<uint8_t >(TestInputDef<float >({1 , 3 , 4 , 4 }, false , GetFloatDataInRange (-10 .0f , 10 .0f , 48 )),
233+ TestInputDef<int64_t >({1 }, true /* is_initializer */ , {2 }),
234+ {utils::MakeAttribute (" axis" , static_cast <int64_t >(1 )),
235+ utils::MakeAttribute (" largest" , static_cast <int64_t >(0 ))}, // Attributes
236+ ExpectedEPNodeAssignment::All);
237+ }
238+
177239// Test 16-bit QDQ TopK on HTP backend: top 2 largest floats from last axis
178240TEST_F (QnnHTPBackendTests, TopK_LargestFloats_U16_LastAxis) {
179241 RunQDQTopKTestOnHTP<uint16_t >(TestInputDef<float >({1 , 3 , 4 , 4 }, false , GetFloatDataInRange (-20 .0f , 20 .0f , 48 )),
@@ -183,6 +245,15 @@ TEST_F(QnnHTPBackendTests, TopK_LargestFloats_U16_LastAxis) {
183245 21 ); // opset
184246}
185247
248+ // Test 16-bit QDQ TopK on HTP backend: top 2 largest floats from last axis. Set largest to 0.
249+ TEST_F (QnnHTPBackendTests, TopK_LargestFloats_U16_LastAxis_Largest_0) {
250+ RunQDQTopKTestOnHTP<uint16_t >(TestInputDef<float >({1 , 3 , 4 , 4 }, false , GetFloatDataInRange (-20 .0f , 20 .0f , 48 )),
251+ TestInputDef<int64_t >({1 }, true /* is_initializer */ , {2 }),
252+ {utils::MakeAttribute (" largest" , static_cast <int64_t >(0 ))}, // Attributes
253+ ExpectedEPNodeAssignment::All,
254+ 21 ); // opset
255+ }
256+
186257// Test 16-bit QDQ TopK on HTP backend: non-last axis
187258TEST_F (QnnHTPBackendTests, TopK_U16_NonLastAxis) {
188259 RunQDQTopKTestOnHTP<uint16_t >(TestInputDef<float >({1 , 3 , 4 , 4 }, false , GetFloatDataInRange (-20 .0f , 20 .0f , 48 )),
@@ -192,6 +263,15 @@ TEST_F(QnnHTPBackendTests, TopK_U16_NonLastAxis) {
192263 21 ); // opset
193264}
194265
266+ // Test 16-bit QDQ TopK on HTP backend: non-last axis. Set largest to 0.
267+ TEST_F (QnnHTPBackendTests, TopK_U16_NonLastAxis_Largest_0) {
268+ RunQDQTopKTestOnHTP<uint16_t >(TestInputDef<float >({1 , 3 , 4 , 4 }, false , GetFloatDataInRange (-20 .0f , 20 .0f , 48 )),
269+ TestInputDef<int64_t >({1 }, true /* is_initializer */ , {2 }),
270+ {utils::MakeAttribute (" axis" , static_cast <int64_t >(1 )),
271+ utils::MakeAttribute (" largest" , static_cast <int64_t >(0 ))}, // Attributes
272+ ExpectedEPNodeAssignment::All,
273+ 21 ); // opset
274+ }
195275#endif // defined(__aarch64__) || defined(_M_ARM64) || defined(__linux__)
196276} // namespace test
197277} // namespace onnxruntime
0 commit comments