-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NPUW: Added conditional checks for accuracy for spatial subgraphs #27348
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,30 +13,47 @@ | |
ov::npuw::metrics::NRMSE::NRMSE(double threshold) : m_threshold(threshold) {} | ||
|
||
bool ov::npuw::metrics::NRMSE::operator()(const ov::SoPtr<ov::ITensor>& actual, | ||
const ov::SoPtr<ov::ITensor>& reference) const { | ||
NPUW_ASSERT(actual->is_continuous()); | ||
NPUW_ASSERT(reference->is_continuous()); | ||
const ov::SoPtr<ov::ITensor>& reference, | ||
double* result) const { | ||
Comment on lines
15
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This For those who were only checking true/false, that type could have |
||
NPUW_ASSERT(actual->get_shape() == reference->get_shape()); | ||
// Check for alignment: | ||
NPUW_ASSERT(actual->get_byte_size() == reference->get_byte_size()); | ||
// FIXME: Check for strides | ||
|
||
ov::Tensor in_actual(actual->get_element_type(), actual->get_shape()); | ||
ov::Tensor in_reference(reference->get_element_type(), reference->get_shape()); | ||
|
||
if (!actual->is_continuous()) { | ||
ov::make_tensor(actual).copy_to(in_actual); | ||
} else { | ||
in_actual = ov::make_tensor(actual); | ||
} | ||
if (!reference->is_continuous()) { | ||
ov::make_tensor(reference).copy_to(in_reference); | ||
} else { | ||
in_reference = ov::make_tensor(reference); | ||
} | ||
|
||
// TODO: it might be more correct to make to_f32 function | ||
// to work with strided tensors | ||
NPUW_ASSERT(in_actual.is_continuous()); | ||
NPUW_ASSERT(in_reference.is_continuous()); | ||
|
||
ov::Tensor actual_f32; | ||
ov::Tensor reference_f32; | ||
|
||
if (ov::element::Type_t::f32 == actual->get_element_type()) { | ||
actual_f32 = ov::make_tensor(actual); | ||
if (ov::element::f32 == in_actual.get_element_type()) { | ||
actual_f32 = in_actual; | ||
} else { | ||
ov::Tensor dst(ov::element::Type_t::f32, actual->get_shape()); | ||
ov::npuw::util::to_f32(ov::make_tensor(actual), dst); | ||
ov::Tensor dst(ov::element::Type_t::f32, in_actual.get_shape()); | ||
ov::npuw::util::to_f32(in_actual, dst); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since you anyways convert to f32, it could be easier to teach this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added TODO, will create a ticket! |
||
actual_f32 = std::move(dst); | ||
} | ||
|
||
if (ov::element::Type_t::f32 == reference->get_element_type()) { | ||
reference_f32 = ov::make_tensor(reference); | ||
if (ov::element::f32 == in_reference.get_element_type()) { | ||
reference_f32 = in_reference; | ||
} else { | ||
ov::Tensor dst(ov::element::Type_t::f32, reference->get_shape()); | ||
ov::npuw::util::to_f32(ov::make_tensor(reference), dst); | ||
ov::Tensor dst(ov::element::Type_t::f32, in_reference.get_shape()); | ||
ov::npuw::util::to_f32(in_reference, dst); | ||
reference_f32 = dst; | ||
} | ||
|
||
|
@@ -51,13 +68,21 @@ bool ov::npuw::metrics::NRMSE::operator()(const ov::SoPtr<ov::ITensor>& actual, | |
} | ||
|
||
if (squared_error <= std::numeric_limits<double>::epsilon()) { | ||
LOG_INFO("NRMSE loss: 0.0, threshold: " << m_threshold << "."); | ||
LOG_INFO("PASS"); | ||
if (result != nullptr) { | ||
*result = 0.0; | ||
} | ||
return true; | ||
} | ||
|
||
double rmse = sqrt(squared_error / size); | ||
NPUW_ASSERT(rmse >= 0.0); | ||
|
||
if (rmse < 0.0) { | ||
// Calculated RMSE metric is < 0.0, what is unexpected. So, return that tensors are unequal. | ||
if (result != nullptr) { | ||
*result = rmse; | ||
} | ||
return false; | ||
} | ||
|
||
auto actual_min_max = std::minmax_element(actual_data, actual_data + size); | ||
auto reference_min_max = std::minmax_element(reference_data, reference_data + size); | ||
|
@@ -66,9 +91,8 @@ bool ov::npuw::metrics::NRMSE::operator()(const ov::SoPtr<ov::ITensor>& actual, | |
std::max(0.f, *actual_min_max.second) - std::min(0.f, *actual_min_max.first)}); | ||
|
||
double nrmse = rmse / den; | ||
LOG_INFO("NRMSE loss: " << nrmse << ", threshold: " << m_threshold << "."); | ||
|
||
bool success = nrmse <= m_threshold; | ||
LOG_INFO((success ? "PASS" : "FAIL")); | ||
return success; | ||
if (result != nullptr) { | ||
*result = nrmse; | ||
} | ||
return nrmse <= m_threshold; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please rephrase. What are the "materials"?
Also, as we operate at subgraph level, there's no "model(s)"