aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Barbier <anthony.barbier@arm.com>2017-11-09 10:29:59 +0000
committerAnthony Barbier <anthony.barbier@arm.com>2018-11-02 16:35:24 +0000
commitab14c15dc9a0f55664fe523aed072fffa60da420 (patch)
treeb5a90018b71d10cd5a7ac2f19acdb34354208baa
parent33da05bc53a3de35c8b2fad04ab78d5b40d6aa77 (diff)
downloadComputeLibrary-ab14c15dc9a0f55664fe523aed072fffa60da420.tar.gz
COMPMID-663: Reworked / cleaned up instuments' measurements
Everything used to be stored as double which led to some numbers appearing in scientific notation and some counters values getting corrupted. Now measurements can be stored as either floating point or integer values. Added support for raw_data in order to output more detailed information to the JSON files (Will make use of that in the OpenCL timer instrument) Change-Id: Ie83776b347a764c8bf45b47d7d9d7bec02b04257 Reviewed-on: http://mpd-gerrit.cambridge.arm.com/95035 Tested-by: Kaizen <jeremy.johnson+kaizengerrit@arm.com> Reviewed-by: Gian Marco Iodice <gianmarco.iodice@arm.com> Reviewed-by: Georgios Pinitas <georgios.pinitas@arm.com>
-rw-r--r--tests/framework/Utils.h16
-rw-r--r--tests/framework/instruments/MaliCounter.cpp12
-rw-r--r--tests/framework/instruments/MaliCounter.h2
-rw-r--r--tests/framework/instruments/Measurement.h223
-rw-r--r--tests/framework/printers/JSONPrinter.cpp33
-rw-r--r--tests/framework/printers/PrettyPrinter.cpp26
6 files changed, 241 insertions, 71 deletions
diff --git a/tests/framework/Utils.h b/tests/framework/Utils.h
index a9fe0dcaa3..4f4b6fce56 100644
--- a/tests/framework/Utils.h
+++ b/tests/framework/Utils.h
@@ -152,6 +152,22 @@ inline std::string tolower(std::string string)
});
return string;
}
+
+/** Create a string with the arithmetic value in full precision.
+ *
+ * @param val Arithmetic value
+ *
+ * @return String with the arithmetic value.
+ */
+template <typename T, typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0>
+inline std::string arithmetic_to_string(T val)
+{
+ std::stringstream ss;
+ ss.precision(std::numeric_limits<T>::digits10 + 1);
+ ss << val;
+ return ss.str();
+}
+
} // namespace framework
} // namespace test
} // namespace arm_compute
diff --git a/tests/framework/instruments/MaliCounter.cpp b/tests/framework/instruments/MaliCounter.cpp
index 6cc3ac5bcb..f36d1801a3 100644
--- a/tests/framework/instruments/MaliCounter.cpp
+++ b/tests/framework/instruments/MaliCounter.cpp
@@ -111,7 +111,7 @@ MaliCounter::MaliCounter()
{
_counters =
{
- { "GPU_ACTIVE", TypedMeasurement<uint64_t>(0, "cycles") },
+ { "GPU_ACTIVE", Measurement(0, "cycles") },
};
_core_counters =
@@ -373,8 +373,8 @@ void MaliCounter::stop()
sample_counters();
wait_next_event();
- const auto counter = get_counters(mali_userspace::MALI_NAME_BLOCK_JM);
- _counters.at("GPU_ACTIVE").value = counter[find_counter_index_by_name(mali_userspace::MALI_NAME_BLOCK_JM, "GPU_ACTIVE")];
+ const uint32_t *counter = get_counters(mali_userspace::MALI_NAME_BLOCK_JM);
+ _counters.at("GPU_ACTIVE") = Measurement(counter[find_counter_index_by_name(mali_userspace::MALI_NAME_BLOCK_JM, "GPU_ACTIVE")], _counters.at("GPU_ACTIVE").unit());
const int arith_index = find_counter_index_by_name(mali_userspace::MALI_NAME_BLOCK_SHADER, "ARITH_WORDS");
const int ls_index = find_counter_index_by_name(mali_userspace::MALI_NAME_BLOCK_SHADER, "LS_ISSUE");
@@ -385,7 +385,7 @@ void MaliCounter::stop()
// Shader core counters can be averaged if desired, but here we don't.
for(int core = 0; core < _num_cores; ++core)
{
- const auto sc_counter = get_counters(mali_userspace::MALI_NAME_BLOCK_SHADER, core);
+ const uint32_t *sc_counter = get_counters(mali_userspace::MALI_NAME_BLOCK_SHADER, core);
_core_counters.at("ARITH_WORDS").values[core] = sc_counter[arith_index];
_core_counters.at("LS_ISSUE").values[core] = sc_counter[ls_index];
@@ -406,7 +406,7 @@ Instrument::MeasurementsMap MaliCounter::measurements() const
{
MeasurementsMap measurements
{
- { "Timespan", TypedMeasurement<uint64_t>(_stop_time - _start_time, "ns") },
+ { "Timespan", Measurement(_stop_time - _start_time, "ns") },
{ "GPU active", _counters.at("GPU_ACTIVE") },
};
@@ -414,7 +414,7 @@ Instrument::MeasurementsMap MaliCounter::measurements() const
{
for(const auto &core : counter.second.values)
{
- measurements.emplace(counter.second.name + " #" + support::cpp11::to_string(core.first), TypedMeasurement<uint64_t>(core.second, counter.second.unit));
+ measurements.emplace(counter.second.name + " #" + support::cpp11::to_string(core.first), Measurement(core.second, counter.second.unit));
}
}
diff --git a/tests/framework/instruments/MaliCounter.h b/tests/framework/instruments/MaliCounter.h
index c7aaa3c4fd..64b5b93015 100644
--- a/tests/framework/instruments/MaliCounter.h
+++ b/tests/framework/instruments/MaliCounter.h
@@ -65,7 +65,7 @@ private:
const uint32_t *get_counters(mali_userspace::MaliCounterBlockName block, int core = -1) const;
int find_counter_index_by_name(mali_userspace::MaliCounterBlockName block, const char *name);
- std::map<std::string, TypedMeasurement<uint64_t>> _counters{};
+ std::map<std::string, Measurement> _counters{};
struct core_counters
{
diff --git a/tests/framework/instruments/Measurement.h b/tests/framework/instruments/Measurement.h
index 324fd51b47..08624f3345 100644
--- a/tests/framework/instruments/Measurement.h
+++ b/tests/framework/instruments/Measurement.h
@@ -25,7 +25,9 @@
#define ARM_COMPUTE_TEST_MEASUREMENT
#include "../Utils.h"
+#include "arm_compute/core/Error.h"
+#include <list>
#include <ostream>
#include <string>
@@ -35,67 +37,204 @@ namespace test
{
namespace framework
{
-/** Abstract measurement.
- *
- * Every measurement needs to define it's unit.
- */
-struct IMeasurement
+/** Generic measurement that stores values as either double or long long int. */
+struct Measurement
{
- /** Constructor.
+ struct Value
+ {
+ /** Constructor
+ *
+ * @param[in] is_floating Will the value stored be floating point ?
+ */
+ Value(bool is_floating)
+ : v{ 0 }, is_floating_point(is_floating)
+ {
+ }
+
+ /** Add the value stored to the stream as a string
+ */
+ friend std::ostream &operator<<(std::ostream &os, const Value &value)
+ {
+ if(value.is_floating_point)
+ {
+ os << arithmetic_to_string(value.v.floating_point);
+ }
+ else
+ {
+ os << arithmetic_to_string(value.v.integer);
+ }
+ return os;
+ }
+ /** Convert the value stored to string
+ */
+ std::string to_string() const
+ {
+ std::stringstream ss;
+ ss << *this;
+ return ss.str();
+ }
+ /** Add with another value and return the sum
+ *
+ * @param[in] b Other value
+ *
+ * @return Sum of the stored value + b
+ */
+ Value operator+(Value b) const
+ {
+ if(is_floating_point)
+ {
+ b.v.floating_point += v.floating_point;
+ }
+ else
+ {
+ b.v.integer += v.integer;
+ }
+ return b;
+ }
+
+ /** Return the stored value divided by an integer.
+ *
+ * @param[in] b Integer to divide the value by.
+ *
+ * @return Stored value / b
+ */
+ Value operator/(int b) const
+ {
+ Value res(is_floating_point);
+ if(is_floating_point)
+ {
+ res.v.floating_point = v.floating_point / b;
+ }
+ else
+ {
+ res.v.integer = v.integer / b;
+ }
+ return res;
+ }
+
+ /** Subtract another value and return the updated stored value.
+ *
+ * @param[in] b Other value
+ *
+ * @return The updated stored value
+ */
+ Value &operator-=(const Value &b)
+ {
+ if(is_floating_point)
+ {
+ v.floating_point -= b.v.floating_point;
+ }
+ else
+ {
+ v.integer -= b.v.integer;
+ }
+ return *this;
+ }
+
+ /** Compare the stored value with another value
+ *
+ * @param[in] b Value to compare against
+ *
+ * @return The result of stored value < b
+ */
+ bool operator<(const Value &b) const
+ {
+ if(is_floating_point)
+ {
+ return v.floating_point < b.v.floating_point;
+ }
+ else
+ {
+ return v.integer < b.v.integer;
+ }
+ }
+
+ /** Stored value */
+ union
+ {
+ double floating_point;
+ long long int integer;
+ } v;
+ bool is_floating_point; /**< Is the stored value floating point or integer ? */
+ };
+
+ /** Stream output operator to print the measurement.
*
- * @param[in] unit Unit of the measurement.
+ * Prints value and unit.
*/
- explicit IMeasurement(std::string unit)
- : unit{ std::move(unit) }
+ friend inline std::ostream &operator<<(std::ostream &os, const Measurement &measurement)
{
+ os << measurement._value << " " << measurement._unit;
+ return os;
}
- std::string unit;
-};
-
-/** Measurement of a specific type. */
-template <typename T>
-struct TypedMeasurement : public IMeasurement
-{
- /** Constructor.
+ /** Constructor to store a floating point value
*
- * @param[in] value Measured value.
- * @param[in] unit Unit of the Measurement.
+ * @param[in] v Value to store
+ * @param[in] unit Unit of @p v
+ * @param[in] raw (Optional) The raw value(s) @p was generated from.
*/
- TypedMeasurement(T value, std::string unit)
- : IMeasurement(std::move(unit)), value{ value }
+ template < typename Floating, typename std::enable_if < !std::is_integral<Floating>::value, int >::type = 0 >
+ Measurement(Floating v, std::string unit, std::list<std::string> raw = {})
+ : _unit(unit), _raw_data(std::move(raw)), _value(true)
{
+ _value.v.floating_point = static_cast<double>(v);
+ if(_raw_data.empty())
+ {
+ _raw_data = { _value.to_string() };
+ }
}
- T value;
-};
+ /** Constructor to store an integer value
+ *
+ * @param[in] v Value to store
+ * @param[in] unit Unit of @p v
+ * @param[in] raw (Optional) The raw value(s) @p was generated from.
+ */
+ template <typename Integer, typename std::enable_if<std::is_integral<Integer>::value, int>::type = 0>
+ Measurement(Integer v, std::string unit, std::list<std::string> raw = {})
+ : _unit(unit), _raw_data(std::move(raw)), _value(false)
+ {
+ _value.v.integer = static_cast<long long int>(v);
+ if(_raw_data.empty())
+ {
+ _raw_data = { _value.to_string() };
+ }
+ }
-/** Stream output operator to print the measurement.
- *
- * Prints value and unit.
- */
-template <typename T>
-inline std::ostream &operator<<(std::ostream &os, const TypedMeasurement<T> &measurement)
-{
- os << measurement.value << measurement.unit;
- return os;
-}
+ /** Accessor for the unit of the measurement
+ *
+ * @return Unit of the measurement
+ */
+ const std::string &unit() const
+ {
+ return _unit;
+ }
-/** Generic measurement that stores values as double. */
-struct Measurement : public TypedMeasurement<double>
-{
- using TypedMeasurement::TypedMeasurement;
+ /** Accessor for the raw data
+ *
+ * @return The raw data
+ */
+ const std::list<std::string> &raw_data() const
+ {
+ return _raw_data;
+ }
- /** Conversion constructor.
+ /** Accessor for the stored value
*
- * @param[in] measurement Typed measurement.
+ * @return The stored value
*/
- template <typename T>
- Measurement(TypedMeasurement<T> measurement)
- : Measurement(measurement.value, measurement.unit)
+ const Value &value() const
{
+ return _value;
}
+
+private:
+ std::string _unit;
+ std::list<std::string> _raw_data;
+ Value _value;
};
+
} // namespace framework
} // namespace test
} // namespace arm_compute
diff --git a/tests/framework/printers/JSONPrinter.cpp b/tests/framework/printers/JSONPrinter.cpp
index 4f17e6277b..bb85a134f2 100644
--- a/tests/framework/printers/JSONPrinter.cpp
+++ b/tests/framework/printers/JSONPrinter.cpp
@@ -164,36 +164,49 @@ void JSONPrinter::print_measurements(const Profiler::MeasurementsMap &measuremen
{
*_stream << R"(")" << i_it->first << R"(" : {)";
- auto add_measurements = [](double a, const Measurement & b)
+ auto add_measurements = [](Measurement::Value a, const Measurement & b)
{
- return a + b.value;
+ return a + b.value();
};
auto cmp_measurements = [](const Measurement & a, const Measurement & b)
{
- return a.value < b.value;
+ return a.value() < b.value();
};
- double sum_values = std::accumulate(i_it->second.cbegin(), i_it->second.cend(), 0., add_measurements);
int num_values = i_it->second.size();
const auto minmax_values = std::minmax_element(i_it->second.begin(), i_it->second.end(), cmp_measurements);
+ Measurement::Value sum_values = std::accumulate(i_it->second.cbegin(), i_it->second.cend(), Measurement::Value(minmax_values.first->value().is_floating_point), add_measurements);
if(num_values > 2)
{
- sum_values -= minmax_values.first->value + minmax_values.second->value;
+ sum_values -= minmax_values.first->value() + minmax_values.second->value();
num_values -= 2;
}
auto measurement_to_string = [](const Measurement & measurement)
{
- return support::cpp11::to_string(measurement.value);
+ if(measurement.raw_data().size() == 1)
+ {
+ return measurement.raw_data().front();
+ }
+ else
+ {
+ std::stringstream str;
+ str << "[";
+ str << join(measurement.raw_data().begin(), measurement.raw_data().end(), ",");
+ str << "]";
+ return str.str();
+ }
};
-
*_stream << R"("avg" : )" << (sum_values / num_values) << ",";
- *_stream << R"("min" : )" << minmax_values.first->value << ",";
- *_stream << R"("max" : )" << minmax_values.second->value << ",";
+ if(num_values > 1)
+ {
+ *_stream << R"("min" : )" << minmax_values.first->value() << ",";
+ *_stream << R"("max" : )" << minmax_values.second->value() << ",";
+ }
*_stream << R"("raw" : [)" << join(i_it->second.begin(), i_it->second.end(), ",", measurement_to_string) << "],";
- *_stream << R"("unit" : ")" << minmax_values.first->unit << R"(")";
+ *_stream << R"("unit" : ")" << minmax_values.first->unit() << R"(")";
*_stream << "}";
if(++i_it != i_end)
diff --git a/tests/framework/printers/PrettyPrinter.cpp b/tests/framework/printers/PrettyPrinter.cpp
index 5eec72a2fe..280813f044 100644
--- a/tests/framework/printers/PrettyPrinter.cpp
+++ b/tests/framework/printers/PrettyPrinter.cpp
@@ -114,32 +114,34 @@ void PrettyPrinter::print_measurements(const Profiler::MeasurementsMap &measurem
{
*_stream << begin_color("3") << " " << instrument.first << ":";
- auto add_measurements = [](double a, const Measurement & b)
+ auto add_measurements = [](Measurement::Value a, const Measurement & b)
{
- return a + b.value;
+ return a + b.value();
};
auto cmp_measurements = [](const Measurement & a, const Measurement & b)
{
- return a.value < b.value;
+ return a.value() < b.value();
};
- double sum_values = std::accumulate(instrument.second.begin(), instrument.second.end(), 0., add_measurements);
- int num_values = instrument.second.size();
- const auto minmax_values = std::minmax_element(instrument.second.begin(), instrument.second.end(), cmp_measurements);
+ int num_values = instrument.second.size();
+ const auto minmax_values = std::minmax_element(instrument.second.begin(), instrument.second.end(), cmp_measurements);
+ Measurement::Value sum_values = std::accumulate(instrument.second.begin(), instrument.second.end(), Measurement::Value(minmax_values.first->value().is_floating_point), add_measurements);
if(num_values > 2)
{
- sum_values -= minmax_values.first->value + minmax_values.second->value;
+ sum_values -= minmax_values.first->value() + minmax_values.second->value();
num_values -= 2;
}
- Measurement avg{ sum_values / num_values, minmax_values.first->unit };
-
*_stream << " ";
- *_stream << "AVG=" << avg << ", ";
- *_stream << "MIN=" << *minmax_values.first << ", ";
- *_stream << "MAX=" << *minmax_values.second << end_color() << "\n";
+ *_stream << "AVG=" << (sum_values / num_values) << " " << minmax_values.second->unit() << ",";
+ if(num_values > 1)
+ {
+ *_stream << "MIN=" << *minmax_values.first << ", ";
+ *_stream << "MAX=" << *minmax_values.second;
+ }
+ *_stream << end_color() << "\n";
}
}
} // namespace framework