From 17acf32b063107a5b23d8d37fd8b5e2142ef8227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Holzm=C3=BCller?= Date: Wed, 10 Apr 2019 11:35:32 +0200 Subject: [PATCH] added files for performance measurement and plotting --- .gitignore | 1 + src/Iterators.hpp | 43 +++++++++++++++++- test/common.hpp | 106 +++++++++++++++++++++++++++++++++++++++++++ test/main.cpp | 106 ++++--------------------------------------- test/performance.cpp | 81 +++++++++++++++++++++++++++++++++ test/plot.py | 32 +++++++++++++ 6 files changed, 270 insertions(+), 99 deletions(-) create mode 100644 test/common.hpp create mode 100644 test/performance.cpp create mode 100644 test/plot.py diff --git a/.gitignore b/.gitignore index 3b23940..68cc33a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ *.auxlock *.dpth *.md5 +*.csv build/* TexCode/* diff --git a/src/Iterators.hpp b/src/Iterators.hpp index e018ba6..937a186 100644 --- a/src/Iterators.hpp +++ b/src/Iterators.hpp @@ -9,7 +9,7 @@ namespace fsi { -size_t binom(size_t n, size_t k) { +inline size_t binom(size_t n, size_t k) { if (2 * k > n) { k = n - k; } @@ -26,6 +26,47 @@ size_t binom(size_t n, size_t k) { return prod; } +template +class StepIterator { + JumpIt jump_it; + size_t first_dim_value; + size_t last_dim_value; + size_t last_dim_count; + size_t tail_dims_counter; + + public: + StepIterator(JumpIt jump_it) + : jump_it(jump_it), + first_dim_value(0), + last_dim_value(0), + last_dim_count(jump_it.lastDimensionCount()), + tail_dims_counter(0){}; + + void next() { + tail_dims_counter += 1; + last_dim_value += 1; + if (last_dim_value >= last_dim_count) { + last_dim_value = 0; + jump_it.next(); + if (jump_it.firstIndex() != first_dim_value) { + first_dim_value = jump_it.firstIndex(); + tail_dims_counter = 0; + } + last_dim_count = jump_it.lastDimensionCount(); + } + } + + bool done() { return jump_it.done(); } + + void reset() { + jump_it.reset(); + first_dim_value = 0; + last_dim_value = 0; + last_dim_count = jump_it.lastDimensionCount(); + tail_dims_counter = 0; + } +}; + template class TemplateBoundedSumIterator { size_t bound; diff --git a/test/common.hpp b/test/common.hpp new file mode 100644 index 0000000..57f44cc --- /dev/null +++ b/test/common.hpp @@ -0,0 +1,106 @@ +// Copyright (C) 2008-today The SG++ project +// This file is part of the SG++ project. For conditions of distribution and +// use, please see the copyright notice provided with SG++ or at +// sgpp.sparsegrids.org + +#pragma once + +#include +#include +#include +#include +#include +#include + +inline double f(std::vector point) { + double prod = 1.0; + for (size_t dim = 0; dim < point.size(); ++dim) { + prod *= point[dim]; + } + return prod; +} + +class GoldenPointDistribution { + static constexpr double golden_ratio = 0.5 * (1.0 + sqrt(5)); + + public: + double operator()(size_t idx) { + double value = (idx + 1) * golden_ratio; + return value - int(value); + } +}; + +class SimplePointDistribution { + public: + double operator()(size_t idx) { + if (idx == 0) { + return 0.0; + } else if (idx == 1) { + return 1.0; + } else { + return 0.5; + } + } +}; + +class MonomialFunctions { + public: + std::function operator()(size_t idx) { + return [=](double x) { return pow(x, idx); }; + } +}; + +template +inline std::ostream &operator<<(std::ostream &os, const std::vector &v) { + os << "["; + for (auto ii = v.begin(); ii != v.end(); ++ii) { + os << " " << *ii; + } + os << " ]"; + return os; +} + +inline std::ostream &operator<<(std::ostream &os, fsi::MultiDimVector const &v) { + for (size_t i = 0; i < v.data.size(); ++i) { + std::cout << v.data[i] << "\n\n"; + } + + return os; +} + +// TODO: refactoring: +/** + * - Interface for MultiDimVector + * - Separate Functions for L- and U-Multiplication, Creation of LU decomposition, computation of + * function values + * - Pass a callback function to iterator instead of calling it.next() - this might improve the + * vector functions (could be made recursive or even loops for fixed dimension implementation) + * - Typed interface? + * - Tests? + * - More point distributions / Basis functions? + * - Forward evaluation? + * - Computation of derivatives? + */ + +inline double measure_execution_time(std::function f) { + auto start = std::chrono::high_resolution_clock::now(); + f(); + auto finish = std::chrono::high_resolution_clock::now(); + std::chrono::duration elapsed = finish - start; + return elapsed.count(); +} + +class Timer { + std::chrono::system_clock::time_point start; + + public: + Timer() : start(std::chrono::high_resolution_clock::now()){}; + void reset() { start = std::chrono::high_resolution_clock::now(); } + double elapsed() { + auto finish = std::chrono::high_resolution_clock::now(); + std::chrono::duration elapsed = finish - start; + return elapsed.count(); + } +}; + +void measurePerformance(); diff --git a/test/main.cpp b/test/main.cpp index 2c9f2d3..e8679b2 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -13,105 +13,9 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include -#include -#include -#include -#include +#include "common.hpp" -double f(std::vector point) { - double prod = 1.0; - for (size_t dim = 0; dim < point.size(); ++dim) { - prod *= point[dim]; - } - return prod; -} - -class GoldenPointDistribution { - static constexpr double golden_ratio = 0.5 * (1.0 + sqrt(5)); - - public: - double operator()(size_t idx) { - double value = (idx + 1) * golden_ratio; - return value - int(value); - } -}; - -class SimplePointDistribution { - public: - double operator()(size_t idx) { - if (idx == 0) { - return 0.0; - } else if (idx == 1) { - return 1.0; - } else { - return 0.5; - } - } -}; - -class MonomialFunctions { - public: - std::function operator()(size_t idx) { - return [=](double x) { return pow(x, idx); }; - } -}; - -template -inline std::ostream &operator<<(std::ostream &os, const std::vector &v) { - os << "["; - for (auto ii = v.begin(); ii != v.end(); ++ii) { - os << " " << *ii; - } - os << " ]"; - return os; -} - -std::ostream &operator<<(std::ostream &os, fsi::MultiDimVector const &v) { - for (size_t i = 0; i < v.data.size(); ++i) { - std::cout << v.data[i] << "\n\n"; - } - - return os; -} - -// TODO: refactoring: -/** - * - Interface for MultiDimVector - * - Separate Functions for L- and U-Multiplication, Creation of LU decomposition, computation of - * function values - * - Pass a callback function to iterator instead of calling it.next() - this might improve the - * vector functions (could be made recursive or even loops for fixed dimension implementation) - * - Typed interface? - * - Tests? - * - More point distributions / Basis functions? - * - Forward evaluation? - * - Computation of derivatives? - */ - -double measure_execution_time(std::function f) { - auto start = std::chrono::high_resolution_clock::now(); - f(); - auto finish = std::chrono::high_resolution_clock::now(); - std::chrono::duration elapsed = finish - start; - return elapsed.count(); -} - -class Timer { - std::chrono::system_clock::time_point start; - - public: - Timer() : start(std::chrono::high_resolution_clock::now()){}; - void reset() { start = std::chrono::high_resolution_clock::now(); } - double elapsed() { - auto finish = std::chrono::high_resolution_clock::now(); - std::chrono::duration elapsed = finish - start; - return elapsed.count(); - } -}; - -// using namespace fsi; -int main() { +void runFunctions() { constexpr size_t d = 8; size_t bound = 24; fsi::TemplateBoundedSumIterator it(bound); @@ -146,3 +50,9 @@ int main() { // std::cout << result.data[i] << "\n\n"; // } } + +// using namespace fsi; +int main() { + // runFunctions(); + measurePerformance(); +} diff --git a/test/performance.cpp b/test/performance.cpp new file mode 100644 index 0000000..4483343 --- /dev/null +++ b/test/performance.cpp @@ -0,0 +1,81 @@ +/* Copyright 2019 The fast_sparse_interpolation Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "common.hpp" + +#include + +double measureRuntime(std::function f, size_t k = 3) { + size_t n = 2 * k + 1; + + std::vector singleResults(n); + for (size_t i = 0; i < n; ++i) { + singleResults[i] = f(); + } + std::sort(singleResults.begin(), singleResults.end()); + // return (singleResults[k-1] + singleResults[k] + + // singleResults[k+1]) / 3.0; + return singleResults[k]; +} + +void measurePerformance() { + // std::vector < size_t > dimensions = {2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64 }; + // std::vector dimensions = {5, 10}; + + std::vector dimensions = {2, 4, 8, 16, 32}; + // size_t maxNumPoints = 20000000; + size_t maxNumPoints = 500000; + + std::ostringstream stream; + + size_t approxNumSteps = 8; + size_t k = 1; + + for (size_t d : dimensions) { + std::cout << "Dimension: " << d << "\n"; + size_t maxBound = 0; + + while (fsi::binom(maxBound + d, d) <= maxNumPoints) { + maxBound += 1; + } + + size_t stepsize = maxBound / approxNumSteps + 1; + + for (size_t bound = 2; bound < maxBound; bound += stepsize) { + std::cout << "Bound: " << bound << "\n"; + double runtime = measureRuntime( + [&]() { + fsi::BoundedSumIterator it(d, bound); + std::vector phi(d); + std::vector x(d); + + auto rhs = evaluateFunction(it, f, x); + auto op = createInterpolationOperator(it, phi, x); + + Timer timer; + op.solve(rhs); + double time = timer.elapsed(); + std::cout << "Time for solve(): " << time << " s\n"; + return time; + }, + k); + + stream << d << ", " << bound << ", " << fsi::binom(bound + d, d) << ", " << runtime << "\n"; + } + } + + std::ofstream file("performance_data.csv"); + file << stream.str(); +} diff --git a/test/plot.py b/test/plot.py new file mode 100644 index 0000000..41edef8 --- /dev/null +++ b/test/plot.py @@ -0,0 +1,32 @@ +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D +import numpy as np +import os.path +import math + + +def readFromFile(filename): + if not os.path.isfile(filename): + return '' + + file = open(filename, 'r') + result = file.read() + file.close() + return result + +datastr = readFromFile("../performance_data.csv") +rows = datastr.split("\n")[:-1] +values = np.array([[float(s) for s in r.split(', ')] for r in rows]) +# print(values) + +dimensions = values[:, 0] +bounds = values[:, 1] +points = values[:, 2] +times = values[:, 3] + +fig = plt.figure() +ax = fig.add_subplot(1,1,1, projection='3d') +surf = ax.plot_trisurf(np.log2(dimensions), np.log2(points), np.log10(times), cmap='viridis', edgecolor='none') +plt.show() + +