aboutsummaryrefslogtreecommitdiff
path: root/reference_model
diff options
context:
space:
mode:
Diffstat (limited to 'reference_model')
-rw-r--r--reference_model/src/generate/generate_utils.cc7
-rw-r--r--reference_model/src/verify/verify_ulp.cc37
-rw-r--r--reference_model/src/verify/verify_utils.cc26
-rw-r--r--reference_model/src/verify/verify_utils.h6
-rw-r--r--reference_model/test/verify_tests.cpp6
5 files changed, 70 insertions, 12 deletions
diff --git a/reference_model/src/generate/generate_utils.cc b/reference_model/src/generate/generate_utils.cc
index c889f7b..fd42f21 100644
--- a/reference_model/src/generate/generate_utils.cc
+++ b/reference_model/src/generate/generate_utils.cc
@@ -38,16 +38,23 @@ NLOHMANN_JSON_SERIALIZE_ENUM(DType,
NLOHMANN_JSON_SERIALIZE_ENUM(Op,
{
{ Op::Op_UNKNOWN, "UNKNOWN" },
+ { Op::Op_ABS, "ABS" },
{ Op::Op_ADD, "ADD" },
{ Op::Op_ARGMAX, "ARGMAX" },
+ { Op::Op_CEIL, "CEIL" },
{ Op::Op_CONV2D, "CONV2D" },
+ { Op::Op_FLOOR, "FLOOR" },
{ Op::Op_FULLY_CONNECTED, "FULLY_CONNECTED" },
+ { Op::Op_IDENTITY, "IDENTITY" },
{ Op::Op_MATMUL, "MATMUL" },
{ Op::Op_MAXIMUM, "MAXIMUM" },
{ Op::Op_MAX_POOL2D, "MAX_POOL2D" },
{ Op::Op_MINIMUM, "MINIMUM" },
{ Op::Op_MUL, "MUL" },
+ { Op::Op_NEGATE, "NEGATE" },
{ Op::Op_PAD, "PAD" },
+ { Op::Op_RECIPROCAL, "RECIPROCAL" },
+ { Op::Op_RSQRT, "RSQRT" },
{ Op::Op_REDUCE_MAX, "REDUCE_MAX" },
{ Op::Op_REDUCE_MIN, "REDUCE_MIN" },
{ Op::Op_REDUCE_SUM, "REDUCE_SUM" },
diff --git a/reference_model/src/verify/verify_ulp.cc b/reference_model/src/verify/verify_ulp.cc
index 8c27191..2af0012 100644
--- a/reference_model/src/verify/verify_ulp.cc
+++ b/reference_model/src/verify/verify_ulp.cc
@@ -16,6 +16,7 @@
#include <limits>
#include <memory>
#include <type_traits>
+#include <utility>
#include "verifiers.h"
@@ -36,9 +37,14 @@ bool tosaCheckULP(double referenceValue, float testValue, double ulpNum)
// Start by sanitizing the input.
- // The concept of ULP isn't defined for NaN's
+ // Both must be NaNs to be correct
if (std::isnan(referenceValue) || std::isnan(testValue))
{
+ if (std::isnan(referenceValue) && std::isnan(testValue))
+ {
+ return true;
+ }
+ WARNING("[Verfier][ULP] Non-matching NaN values - ref (%10f) versus test (%10f).", referenceValue, testValue);
return false;
}
@@ -112,8 +118,8 @@ bool tosaCheckULP(double referenceValue, float testValue, double ulpNum)
bool withinUlp = testValue64 >= referenceMin && testValue64 <= referenceMax;
if (!withinUlp)
{
- WARNING("[Verfier][ULP] value (%10f) is not in ULP %g range (%10f <= ref (%10f) <= %10f).", testValue64, ulpNum,
- referenceMin, referenceValue, referenceMax);
+ WARNING("[Verfier][ULP] value (%10.10f) is not in ULP %g range (%10.10f <= ref (%10.10f) <= %10.10f).",
+ testValue64, ulpNum, referenceMin, referenceValue, referenceMax);
}
return withinUlp;
}
@@ -126,8 +132,8 @@ bool verifyULP(const CTensor* referenceTensor, const CTensor* implementationTens
TOSA_REF_REQUIRE(implementationTensor != nullptr, "[ULP] Implementation tensor is missing");
// Get number of elements
- const auto elementCount =
- numElements(std::vector<int32_t>(referenceTensor->shape, referenceTensor->shape + referenceTensor->num_dims));
+ const std::vector<int32_t> refShape(referenceTensor->shape, referenceTensor->shape + referenceTensor->num_dims);
+ const auto elementCount = numElements(refShape);
TOSA_REF_REQUIRE(elementCount > 0, "[ULP] Invalid shape for reference tensor");
const double ulp = ulpInfo.ulp;
@@ -138,10 +144,23 @@ bool verifyULP(const CTensor* referenceTensor, const CTensor* implementationTens
TOSA_REF_REQUIRE(refData != nullptr, "[ULP] Missing data for reference");
const auto* impData = reinterpret_cast<const float*>(implementationTensor->data);
TOSA_REF_REQUIRE(impData != nullptr, "[ULP] Missing data for implementation");
- return std::equal(refData, std::next(refData, elementCount), impData, std::next(impData, elementCount),
- [ulp](const auto& referenceValue, const auto& implementationValue) {
- return tosaCheckULP(referenceValue, implementationValue, ulp);
- });
+ const auto* refDataEnd = std::next(refData, elementCount);
+ // Use mismatch to get the location of the first unequal value
+ auto pair = std::mismatch(refData, refDataEnd, impData, std::next(impData, elementCount),
+ [ulp](const auto& referenceValue, const auto& implementationValue) {
+ return tosaCheckULP(referenceValue, implementationValue, ulp);
+ });
+ if (std::get<0>(pair) == refDataEnd)
+ {
+ // No mismatch found
+ return true;
+ }
+ else
+ {
+ auto pos = indexToPosition(std::get<0>(pair) - refData, refShape);
+ WARNING("[Verfier][ULP] Location %s", positionToString(pos).c_str());
+ return false;
+ }
}
default:
WARNING("[Verifier][ULP] Data-type not supported.");
diff --git a/reference_model/src/verify/verify_utils.cc b/reference_model/src/verify/verify_utils.cc
index 99cb0c1..9b20fb2 100644
--- a/reference_model/src/verify/verify_utils.cc
+++ b/reference_model/src/verify/verify_utils.cc
@@ -121,6 +121,32 @@ int64_t numElements(const std::vector<int32_t>& shape)
return std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<int64_t>());
}
+std::vector<int32_t> indexToPosition(int64_t index, const std::vector<int32_t>& shape)
+{
+ std::vector<int32_t> pos;
+ for (auto d = shape.end() - 1; d >= shape.begin(); --d)
+ {
+ pos.insert(pos.begin(), index % *d);
+ index /= *d;
+ }
+ return pos;
+}
+
+std::string positionToString(const std::vector<int32_t>& pos)
+{
+ std::string str = "[";
+ for (auto d = pos.begin(); d < pos.end(); ++d)
+ {
+ str.append(std::to_string(*d));
+ if (pos.end() - d > 1)
+ {
+ str.append(",");
+ }
+ }
+ str.append("]");
+ return str;
+}
+
DType mapToDType(tosa_datatype_t dataType)
{
static std::map<tosa_datatype_t, DType> typeMap = {
diff --git a/reference_model/src/verify/verify_utils.h b/reference_model/src/verify/verify_utils.h
index 15d7ba5..24d65b0 100644
--- a/reference_model/src/verify/verify_utils.h
+++ b/reference_model/src/verify/verify_utils.h
@@ -91,6 +91,12 @@ std::optional<VerifyConfig> parseVerifyConfig(const char* tensorName, const char
/// \brief Extract number of total elements
int64_t numElements(const std::vector<int32_t>& shape);
+/// \brief Convert a flat index to a shape position
+std::vector<int32_t> indexToPosition(int64_t index, const std::vector<int32_t>& shape);
+
+/// \brief A string representing the shape or position
+std::string positionToString(const std::vector<int32_t>& pos);
+
/// \brief Map API data-type to DType
DType mapToDType(tosa_datatype_t dataType);
diff --git a/reference_model/test/verify_tests.cpp b/reference_model/test/verify_tests.cpp
index e7d6c4e..31e27c0 100644
--- a/reference_model/test/verify_tests.cpp
+++ b/reference_model/test/verify_tests.cpp
@@ -392,7 +392,7 @@ TEST_CASE("positive - ulp")
const auto elementCount = std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<>());
// Generate some random floats using the full range of fp32.
- auto data_fp32 = generateRandomTensorData<float>(elementCount, false);
+ auto data_fp32 = generateRandomTensorData<float>(elementCount, true);
std::vector<double> data_fp64(data_fp32.begin(), data_fp32.end());
SUBCASE("same")
@@ -400,7 +400,7 @@ TEST_CASE("positive - ulp")
// Generate some data that meets the ULP requirements of the result.
auto otherData_fp32 = data_fp32;
std::for_each(std::begin(otherData_fp32), std::end(otherData_fp32), [](auto& value) {
- if (std::abs(value) != 0.0 && !std::isinf(value))
+ if (std::abs(value) != 0.0 && !std::isinf(value) && !std::isnan(value))
value = increment(value, 5);
});
const auto referenceTensor =
@@ -415,7 +415,7 @@ TEST_CASE("positive - ulp")
// Generate some data that exceeds a specified number of ULP for each value in the tensor.
auto otherData_fp32 = data_fp32;
std::for_each(std::begin(otherData_fp32), std::end(otherData_fp32), [](auto& value) {
- if (std::abs(value) != 0.0 && !std::isinf(value))
+ if (std::abs(value) != 0.0 && !std::isinf(value) && !std::isnan(value))
value = increment(value, 6);
});