mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-07-30 20:18:08 +00:00
Enable int32 data support for Clip (#20590)
Enable int32 data support for Clip fix issue: https://github.com/microsoft/onnxruntime/issues/20525
This commit is contained in:
parent
d693aef39e
commit
d121a1f906
2 changed files with 86 additions and 29 deletions
|
|
@ -43,15 +43,51 @@ static Status ProcessClipMinMax(QnnModelWrapper& qnn_model_wrapper,
|
|||
std::vector<uint8_t> val_bytes;
|
||||
ORT_RETURN_IF_ERROR(qnn_model_wrapper.GetTensorInfo(input, input_info));
|
||||
assert(input_info.is_initializer); // Checked by ExplicitOpCheck().
|
||||
if (QNN_DATATYPE_FLOAT_16 == input_info.qnn_data_type) {
|
||||
ORT_RETURN_IF_ERROR(qnn_model_wrapper.UnpackInitializerData(*input_info.initializer_tensor, val_bytes));
|
||||
MLFloat16 fp16_value = *reinterpret_cast<const MLFloat16*>(val_bytes.data());
|
||||
float_value = fp16_value.ToFloat();
|
||||
} else {
|
||||
ORT_RETURN_IF_NOT(QNN_DATATYPE_FLOAT_32 == input_info.qnn_data_type,
|
||||
"QNN EP: The 'min' input of the Clip operator must be of type float32.");
|
||||
ORT_RETURN_IF_ERROR(qnn_model_wrapper.UnpackInitializerData(*input_info.initializer_tensor, val_bytes));
|
||||
float_value = *reinterpret_cast<const float*>(val_bytes.data());
|
||||
ORT_RETURN_IF_ERROR(qnn_model_wrapper.UnpackInitializerData(*input_info.initializer_tensor, val_bytes));
|
||||
switch (input_info.qnn_data_type) {
|
||||
case QNN_DATATYPE_INT_8: {
|
||||
float_value = static_cast<float>(*reinterpret_cast<int8_t*>(val_bytes.data()));
|
||||
break;
|
||||
}
|
||||
case QNN_DATATYPE_INT_16: {
|
||||
float_value = static_cast<float>(*reinterpret_cast<int16_t*>(val_bytes.data()));
|
||||
break;
|
||||
}
|
||||
case QNN_DATATYPE_INT_32: {
|
||||
float_value = static_cast<float>(*reinterpret_cast<int32_t*>(val_bytes.data()));
|
||||
break;
|
||||
}
|
||||
case QNN_DATATYPE_INT_64: {
|
||||
float_value = static_cast<float>(*reinterpret_cast<int64_t*>(val_bytes.data()));
|
||||
break;
|
||||
}
|
||||
case QNN_DATATYPE_UINT_8: {
|
||||
float_value = static_cast<float>(*val_bytes.data());
|
||||
break;
|
||||
}
|
||||
case QNN_DATATYPE_UINT_16: {
|
||||
float_value = static_cast<float>(*reinterpret_cast<uint16_t*>(val_bytes.data()));
|
||||
break;
|
||||
}
|
||||
case QNN_DATATYPE_UINT_32: {
|
||||
float_value = static_cast<float>(*reinterpret_cast<uint32_t*>(val_bytes.data()));
|
||||
break;
|
||||
}
|
||||
case QNN_DATATYPE_UINT_64: {
|
||||
float_value = static_cast<float>(*reinterpret_cast<uint64_t*>(val_bytes.data()));
|
||||
break;
|
||||
}
|
||||
case QNN_DATATYPE_FLOAT_16: {
|
||||
MLFloat16 fp16_value = *reinterpret_cast<const MLFloat16*>(val_bytes.data());
|
||||
float_value = fp16_value.ToFloat();
|
||||
break;
|
||||
}
|
||||
case QNN_DATATYPE_FLOAT_32: {
|
||||
float_value = *reinterpret_cast<const float*>(val_bytes.data());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "min/max input data type not supported.");
|
||||
}
|
||||
|
||||
return Status::OK();
|
||||
|
|
|
|||
|
|
@ -17,16 +17,17 @@ namespace test {
|
|||
// Runs a model with a Clip operator on the QNN CPU backend. Checks the graph node assignment
|
||||
// and that inference outputs for QNN EP and CPU EP match.
|
||||
template <typename DataType>
|
||||
static void RunClipTestOnCPU(const TestInputDef<DataType>& input_def,
|
||||
const std::vector<TestInputDef<DataType>>& min_max_defs,
|
||||
ExpectedEPNodeAssignment expected_ep_assignment,
|
||||
int opset = 13) {
|
||||
static void RunClipTest(const TestInputDef<DataType>& input_def,
|
||||
const std::vector<TestInputDef<DataType>>& min_max_defs,
|
||||
ExpectedEPNodeAssignment expected_ep_assignment,
|
||||
bool on_cpu_backend = true,
|
||||
int opset = 13) {
|
||||
ProviderOptions provider_options;
|
||||
|
||||
#if defined(_WIN32)
|
||||
provider_options["backend_path"] = "QnnCpu.dll";
|
||||
provider_options["backend_path"] = on_cpu_backend ? "QnnCpu.dll" : "QnnHtp.dll";
|
||||
#else
|
||||
provider_options["backend_path"] = "libQnnCpu.so";
|
||||
provider_options["backend_path"] = on_cpu_backend ? "libQnnCpu.so" : "libQnnHtp.so";
|
||||
#endif
|
||||
|
||||
RunQnnModelTest(BuildOpTestCase<DataType, DataType>("Clip", {input_def}, min_max_defs, {}),
|
||||
|
|
@ -42,29 +43,29 @@ static void RunClipTestOnCPU(const TestInputDef<DataType>& input_def,
|
|||
// Test that Clip with a dynamic min or max input is not supported by QNN EP.
|
||||
TEST_F(QnnCPUBackendTests, Clip_Dynamic_MinMax_Unsupported) {
|
||||
// Dynamic min input is not supported.
|
||||
RunClipTestOnCPU<float>(TestInputDef<float>({1, 3, 4, 4}, false, -10.0f, 10.0f),
|
||||
{TestInputDef<float>({}, false /* is_initializer */, {-5.0f})},
|
||||
ExpectedEPNodeAssignment::None); // Should not be assigned to QNN EP.
|
||||
RunClipTest<float>(TestInputDef<float>({1, 3, 4, 4}, false, -10.0f, 10.0f),
|
||||
{TestInputDef<float>({}, false /* is_initializer */, {-5.0f})},
|
||||
ExpectedEPNodeAssignment::None); // Should not be assigned to QNN EP.
|
||||
// Dynamic max input is not supported.
|
||||
RunClipTestOnCPU<float>(TestInputDef<float>({1, 3, 4, 4}, false, -10.0f, 10.0f),
|
||||
{TestInputDef<float>({}, true, {-5.0f}),
|
||||
TestInputDef<float>({}, false, {5.0f})},
|
||||
ExpectedEPNodeAssignment::None); // Should not be assigned to QNN EP.
|
||||
RunClipTest<float>(TestInputDef<float>({1, 3, 4, 4}, false, -10.0f, 10.0f),
|
||||
{TestInputDef<float>({}, true, {-5.0f}),
|
||||
TestInputDef<float>({}, false, {5.0f})},
|
||||
ExpectedEPNodeAssignment::None); // Should not be assigned to QNN EP.
|
||||
}
|
||||
|
||||
// Test Clip with default min/max.
|
||||
TEST_F(QnnCPUBackendTests, Clip_4D_f32_DefaultMinMax) {
|
||||
RunClipTestOnCPU<float>(TestInputDef<float>({1, 3, 4, 4}, false, GetFloatDataInRange(-10.0f, 10.0f, 48)),
|
||||
{}, // Don't specify min/max inputs.
|
||||
ExpectedEPNodeAssignment::All);
|
||||
RunClipTest<float>(TestInputDef<float>({1, 3, 4, 4}, false, GetFloatDataInRange(-10.0f, 10.0f, 48)),
|
||||
{}, // Don't specify min/max inputs.
|
||||
ExpectedEPNodeAssignment::All);
|
||||
}
|
||||
|
||||
// Test Clip with 5D input.
|
||||
TEST_F(QnnCPUBackendTests, Clip_5D_f32) {
|
||||
RunClipTestOnCPU<float>(TestInputDef<float>({1, 1, 3, 4, 4}, false, GetFloatDataInRange(-10.0f, 10.0f, 48)),
|
||||
{TestInputDef<float>({}, true, {-5.0f}),
|
||||
TestInputDef<float>({}, true, {5.0f})},
|
||||
ExpectedEPNodeAssignment::All);
|
||||
RunClipTest<float>(TestInputDef<float>({1, 1, 3, 4, 4}, false, GetFloatDataInRange(-10.0f, 10.0f, 48)),
|
||||
{TestInputDef<float>({}, true, {-5.0f}),
|
||||
TestInputDef<float>({}, true, {5.0f})},
|
||||
ExpectedEPNodeAssignment::All);
|
||||
}
|
||||
|
||||
#if defined(__aarch64__) || defined(_M_ARM64) || defined(__linux__)
|
||||
|
|
@ -72,6 +73,26 @@ TEST_F(QnnCPUBackendTests, Clip_5D_f32) {
|
|||
// HTP tests:
|
||||
//
|
||||
|
||||
// Test Clip with float32 on HTP
|
||||
TEST_F(QnnHTPBackendTests, Clip_f32) {
|
||||
bool on_cpu_backend = false;
|
||||
RunClipTest<float>(TestInputDef<float>({1, 1, 3, 4}, false, GetFloatDataInRange(-10.0f, 10.0f, 12)),
|
||||
{TestInputDef<float>({}, true, {-5.0f}),
|
||||
TestInputDef<float>({}, true, {5.0f})},
|
||||
ExpectedEPNodeAssignment::All,
|
||||
on_cpu_backend);
|
||||
}
|
||||
|
||||
// Test Clip with int32 on HTP
|
||||
TEST_F(QnnHTPBackendTests, Clip_int32) {
|
||||
bool on_cpu_backend = false;
|
||||
RunClipTest<int32_t>(TestInputDef<int32_t>({1, 1, 3, 2}, false, {1, 2, -5, 3, -10, 25}),
|
||||
{TestInputDef<int32_t>({}, true, {-5}),
|
||||
TestInputDef<int32_t>({}, true, {5})},
|
||||
ExpectedEPNodeAssignment::All,
|
||||
on_cpu_backend);
|
||||
}
|
||||
|
||||
// Runs a QDQ Clip model on the QNN (HTP) EP and the ORT CPU EP. Checks the graph node assignment and that inference
|
||||
// running the QDQ model on QNN EP is at least as accurate as on ORT CPU EP (compared to the baseline float32 model).
|
||||
template <typename QType>
|
||||
|
|
|
|||
Loading…
Reference in a new issue