]> https://gitweb.dealii.org/ - dealii.git/commitdiff
performance_test_driver.h: Add support for unsigned long long measurements
authorMatthias Maier <tamiko@43-1.org>
Sun, 20 Feb 2022 18:19:39 +0000 (12:19 -0600)
committerMatthias Maier <tamiko@43-1.org>
Fri, 11 Mar 2022 21:46:34 +0000 (15:46 -0600)
tests/performance/performance_test_driver.h
tests/performance/timing_step_22.cc
tests/performance/timing_step_3.cc
tests/performance/timing_step_37.cc
tests/performance/valgrind_instrumentation.h

index 3e22e513f2912cc0309e8c1e4a8de02273338beb..09da47fc2e611a9039579311db2e4334ec678aa3 100644 (file)
@@ -25,6 +25,7 @@
 #include <boost/range/adaptor/indexed.hpp>
 
 #include <algorithm>
+#include <initializer_list>
 #include <iostream>
 #include <numeric>
 #include <string>
@@ -76,6 +77,9 @@ enum class Metric
 {
   /** a timing (wall clock time / cpu time) in seconds */
   timing,
+
+  /** an instruction count (instrumented for example with callgrind) */
+  instruction_count,
 };
 
 
@@ -91,12 +95,26 @@ describe_measurements();
 
 
 /**
- * The Measurement type returned by perform_single_measurement(). This is
- * currently just a typedef for <code>std::vector<double></code> but could
- * be easily extended to a std::variant (or similar) data type supporting
- * something else than double.
+ * The Measurement type returned by perform_single_measurement(). We
+ * support returning a <code>std::vector<double></code> for timings or a
+ * <code>std::vector<unsigned long long></code> for instruction counts.
+ *
+ * Note that the following could be improved using std::variant once we
+ * switch to C++17.
  */
-using Measurement = std::vector<double>;
+struct Measurement
+{
+  Measurement(std::initializer_list<double> results)
+    : timing(results)
+  {}
+
+  Measurement(std::initializer_list<unsigned long long> results)
+    : instruction_count(results)
+  {}
+
+  std::vector<double>             timing;
+  std::vector<unsigned long long> instruction_count;
+};
 
 
 /**
@@ -135,12 +153,13 @@ main(int argc, char *argv[])
   const auto number_of_repetitions = std::get<1>(description);
   const auto names                 = std::get<2>(description);
 
-  Assert(number_of_repetitions > 0, dealii::ExcInternalError);
-  if (number_of_repetitions == 0)
-    {
-      pout << "Test specified an invalid number of measurements." << std::endl;
-      return 1;
-    }
+  AssertThrow(number_of_repetitions > 0,
+              dealii::ExcMessage(
+                "Test specified an invalid number of measurements."));
+
+  AssertThrow(metric != Metric::instruction_count || number_of_repetitions == 1,
+              dealii::ExcMessage(
+                "Test specified an invalid number of measurements."));
 
   // Print the measurement type:
 
@@ -149,6 +168,9 @@ main(int argc, char *argv[])
       case Metric::timing:
         pout << "timing\n";
         break;
+      case Metric::instruction_count:
+        pout << "instruction_count\n";
+        break;
     }
 
   // Header:
@@ -171,39 +193,50 @@ main(int argc, char *argv[])
 
   for (std::size_t i = 0; i < names.size(); ++i)
     {
-      const double x = measurements[0][i];
-
-      if (number_of_repetitions == 1)
-        {
-          pout << names[i] << "\t" << x << "\n";
-        }
-      else
+      switch (metric)
         {
-          double min      = x;
-          double max      = x;
-          double mean     = x;
-          double variance = 0.;
-
-          for (unsigned int k = 1; k < number_of_repetitions; ++k)
-            {
-              const double x = measurements[k][i];
-
-              min = std::min(min, x);
-              max = std::max(max, x);
-
-              const auto new_mean = mean + (x - mean) / (k + 1);
-
-              variance = variance + (x - mean) * (x - new_mean);
-              mean     = new_mean;
-            }
-
-          const double std_dev =
-            number_of_repetitions == 1 ?
-              0. :
-              std::sqrt(variance / (number_of_repetitions - 1));
-
-          pout << names[i] << "\t" << min << "\t" << max << "\t" << mean << "\t"
-               << std_dev << "\t" << number_of_repetitions << "\n";
+          case Metric::timing:
+            if (number_of_repetitions == 1)
+              {
+                const double x = measurements[0].timing[i];
+                pout << names[i] << "\t" << x << "\n";
+              }
+            else
+              {
+                const double x        = measurements[0].timing[i];
+                double       min      = x;
+                double       max      = x;
+                double       mean     = x;
+                double       variance = 0.;
+
+                for (unsigned int k = 1; k < number_of_repetitions; ++k)
+                  {
+                    const double x = measurements[k].timing[i];
+
+                    min = std::min(min, x);
+                    max = std::max(max, x);
+
+                    const auto new_mean = mean + (x - mean) / (k + 1);
+
+                    variance = variance + (x - mean) * (x - new_mean);
+                    mean     = new_mean;
+                  }
+
+                const double std_dev =
+                  number_of_repetitions == 1 ?
+                    0. :
+                    std::sqrt(variance / (number_of_repetitions - 1));
+
+                pout << names[i] << "\t" << min << "\t" << max << "\t" << mean
+                     << "\t" << std_dev << "\t" << number_of_repetitions
+                     << "\n";
+              }
+            break;
+
+          case Metric::instruction_count:
+            const unsigned long long x = measurements[0].instruction_count[i];
+            pout << names[i] << "\t" << x << "\n";
+            break;
         }
     }
 
index c8b8a20b2424faa55c24ec59aa4b851005358022..4631e48a3b175f176e1df7fe17c9d9ca2e4a0dd5 100644 (file)
@@ -86,7 +86,7 @@ class StokesProblem
 {
 public:
   StokesProblem(const unsigned int degree);
-  std::vector<double>
+  Measurement
   run();
 
 private:
@@ -574,7 +574,7 @@ StokesProblem<dim>::refine_mesh()
 
 
 template <int dim>
-std::vector<double>
+Measurement
 StokesProblem<dim>::run()
 {
   std::map<std::string, dealii::Timer> timer;
index 86ed67c3054739e536fd94ec034ee779eda60e88..609ab92affe9d59bf37179e2763567c2bce1107a 100644 (file)
@@ -57,7 +57,7 @@ class Step3
 public:
   Step3();
 
-  std::vector<double>
+  Measurement
   run();
 
 private:
@@ -212,7 +212,7 @@ Step3::output_results() const
 }
 
 
-std::vector<double>
+Measurement
 Step3::run()
 {
   std::map<std::string, dealii::Timer> timer;
index 9fb9d8c3763ac7d501dc4e0e1f00d333d306838e..e901033bb84e86a33cef016ae5f73fa4c0eea4a9 100644 (file)
@@ -304,7 +304,8 @@ class LaplaceProblem
 {
 public:
   LaplaceProblem();
-  std::vector<double>
+
+  Measurement
   run();
 
 private:
@@ -588,7 +589,7 @@ LaplaceProblem<dim>::solve()
 
 
 template <int dim>
-std::vector<double>
+Measurement
 LaplaceProblem<dim>::run()
 {
   std::map<std::string, dealii::Timer> timer;
index 7ee4bce7d65c5b2f93c126aa49316c01c7a002f6..31132441b90b62ecb7d18b6aeb0cb15cdf032798 100644 (file)
 #ifndef dealii_valgrind_instrumentation_h
 #define dealii_valgrind_instrumentation_h
 
+#include <deal.II/base/config.h>
+
+#include <deal.II/base/exceptions.h>
+
 #include <unistd.h>
 #include <valgrind/callgrind.h>
 

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.