From d049a0943bc7b171d052ff27cfeebac384cf6c2d Mon Sep 17 00:00:00 2001 From: "Yuhsiang M. Tsai" Date: Mon, 14 Dec 2020 16:38:48 +0100 Subject: [PATCH] use second and double precision of timing result --- benchmark/preconditioner/preconditioner.cpp | 11 +-- benchmark/utils/chrono_utils.hpp | 62 +++++++++++++++++ benchmark/utils/loggers.hpp | 11 +-- benchmark/utils/timer.hpp | 76 +++++++++++---------- 4 files changed, 106 insertions(+), 54 deletions(-) create mode 100644 benchmark/utils/chrono_utils.hpp diff --git a/benchmark/preconditioner/preconditioner.cpp b/benchmark/preconditioner/preconditioner.cpp index 81bcc2f78b4..9bef693fd51 100644 --- a/benchmark/preconditioner/preconditioner.cpp +++ b/benchmark/preconditioner/preconditioner.cpp @@ -171,11 +171,8 @@ void run_preconditioner(const char *precond_name, // the timer is out of the loops to reduce calling synchronize // overhead, so the timer does not know the number of repetitions. - // get_total_time() and compute_average_time() have the same result - // but in different type. We use compute_average_time to eliminate - // the type-casting here. auto generate_time = - generate_timer->compute_average_time() / FLAGS_repetitions; + generate_timer->get_total_time() / FLAGS_repetitions; add_or_set_member(this_precond_data["generate"], "time", generate_time, allocator); @@ -188,11 +185,7 @@ void run_preconditioner(const char *precond_name, // the timer is out of the loops to reduce calling synchronize // overhead, so the timer does not know the number of repetitions. - // get_total_time() and compute_average_time() have the same result - // but in different type. We use compute_average_time to eliminate - // the type-casting here. - auto apply_time = - apply_timer->compute_average_time() / FLAGS_repetitions; + auto apply_time = apply_timer->get_total_time() / FLAGS_repetitions; add_or_set_member(this_precond_data["apply"], "time", apply_time, allocator); } diff --git a/benchmark/utils/chrono_utils.hpp b/benchmark/utils/chrono_utils.hpp new file mode 100644 index 00000000000..a2ade3f4a7f --- /dev/null +++ b/benchmark/utils/chrono_utils.hpp @@ -0,0 +1,62 @@ +/************************************************************* +Copyright (c) 2017-2020, the Ginkgo authors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*************************************************************/ + +#ifndef GKO_BENCHMARK_UTILS_CHRONO_UTILS_HPP_ +#define GKO_BENCHMARK_UTILS_CHRONO_UTILS_HPP_ + + +#include + + +namespace { + + +/** + * Get the seconds of duration in double precision. + * + * @param duration the chrono::steady_clock::duration + * + * @return the seconds of duration in double precision. + */ +double get_duration_in_seconds(std::chrono::steady_clock::duration time) +{ + auto counts = + std::chrono::duration_cast(time).count(); + constexpr int sec_in_ns = 1e9; + return static_cast(counts) / sec_in_ns; +} + + +} // namespace + + +#endif // GKO_BENCHMARK_UTILS_CHRONO_UTILS_HPP_ diff --git a/benchmark/utils/loggers.hpp b/benchmark/utils/loggers.hpp index ea6bbea2797..3c05bac4ce7 100644 --- a/benchmark/utils/loggers.hpp +++ b/benchmark/utils/loggers.hpp @@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include "benchmark/utils/chrono_utils.hpp" #include "benchmark/utils/general.hpp" @@ -109,11 +110,7 @@ struct OperationLogger : gko::log::Logger { for (const auto &entry : total) { add_or_set_member( object, entry.first.c_str(), - std::chrono::duration_cast( - entry.second) - .count() / - repetitions, - alloc); + get_duration_in_seconds(entry.second) / repetitions, alloc); } } @@ -208,9 +205,7 @@ struct ResidualLogger : gko::log::Logger { const gko::LinOp *residual_norm) const override { timestamps.PushBack( - std::chrono::duration_cast( - std::chrono::steady_clock::now() - start) - .count(), + get_duration_in_seconds(std::chrono::steady_clock::now() - start), alloc); if (residual_norm) { rec_res_norms.PushBack( diff --git a/benchmark/utils/timer.hpp b/benchmark/utils/timer.hpp index 4480b6f19cd..9019de50e8e 100644 --- a/benchmark/utils/timer.hpp +++ b/benchmark/utils/timer.hpp @@ -40,6 +40,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include "benchmark/utils/chrono_utils.hpp" + + #ifdef HAS_CUDA @@ -98,47 +101,46 @@ class Timer { } /** - * Get the summation of each time in nanoseconds. + * Get the summation of each time in seconds. * - * @return the nanoseconds of total time + * @return the seconds of total time */ - std::int64_t get_total_time() const { return total_duration_ns_; } + double get_total_time() const { return total_duration_sec_; } /** * Get the number of repetitions. * * @return the number of repetitions */ - std::int64_t get_num_repetitions() const { return duration_ns_.size(); } + std::int64_t get_num_repetitions() const { return duration_sec_.size(); } /** - * Compute the average time of repetitions in nanoseconds + * Compute the average time of repetitions in seconds * - * @return the average time in nanoseconds + * @return the average time in seconds */ double compute_average_time() const { - return static_cast(this->get_total_time()) / - this->get_num_repetitions(); + return this->get_total_time() / this->get_num_repetitions(); } /** - * Get the vector containing the time of each repetition in nanoseconds. + * Get the vector containing the time of each repetition in seconds. * - * @return the vector of time for each repetition in nanoseconds + * @return the vector of time for each repetition in seconds */ - std::vector get_time_detail() const { return duration_ns_; } + std::vector get_time_detail() const { return duration_sec_; } /** - * Get the latest result in nanoseconds. If there is no result yet, return + * Get the latest result in seconds. If there is no result yet, return * 0. * - * @return the latest result in nanoseconds + * @return the latest result in seconds */ - std::int64_t get_latest_time() const + double get_latest_time() const { - if (duration_ns_.size() >= 1) { - return duration_ns_.back(); + if (duration_sec_.size() >= 1) { + return duration_sec_.back(); } else { return 0; } @@ -149,27 +151,27 @@ class Timer { */ void clear() { - duration_ns_.clear(); + duration_sec_.clear(); tic_called_ = false; - total_duration_ns_ = 0; + total_duration_sec_ = 0; } /** * Create a timer */ - Timer() : tic_called_(false), total_duration_ns_(0) {} + Timer() : tic_called_(false), total_duration_sec_(0) {} protected: /** - * Put the nanosecond result into vector + * Put the second result into vector * - * @param ns the nanosecond result to insert + * @param ns the second result to insert */ - void add_record(std::int64_t ns) + void add_record(double ns) { // add the result; - duration_ns_.emplace_back(ns); - total_duration_ns_ += ns; + duration_sec_.emplace_back(ns); + total_duration_sec_ += ns; } /** @@ -178,16 +180,16 @@ class Timer { virtual void tic_impl() = 0; /** - * The implementation of toc. Return the nanoseconds result. + * The implementation of toc. Return the seconds result. * - * @return the nanoseconds result + * @return the seconds result */ - virtual std::int64_t toc_impl() = 0; + virtual double toc_impl() = 0; private: - std::vector duration_ns_; + std::vector duration_sec_; bool tic_called_; - std::int64_t total_duration_ns_; + double total_duration_sec_; }; @@ -212,13 +214,11 @@ class CpuTimer : public Timer { start_ = std::chrono::steady_clock::now(); } - std::int64_t toc_impl() override + double toc_impl() override { exec_->synchronize(); auto stop = std::chrono::steady_clock::now(); - auto duration_time = - std::chrono::duration_cast(stop - start_) - .count(); + auto duration_time = get_duration_in_seconds(stop - start_); return duration_time; } @@ -268,7 +268,7 @@ class CudaTimer : public Timer { GKO_ASSERT_NO_CUDA_ERRORS(cudaEventRecord(start_)); } - std::int64_t toc_impl() override + double toc_impl() override { gko::cuda::device_guard g{id_}; // Currently, gko::CudaExecutor always use default stream. @@ -279,7 +279,8 @@ class CudaTimer : public Timer { // resolution of around 0.5 microseconds GKO_ASSERT_NO_CUDA_ERRORS( cudaEventElapsedTime(&duration_time, start_, stop_)); - return static_cast(duration_time * 1e6); + constexpr int sec_in_ms = 1e3; + return static_cast(duration_time) / sec_in_ms); } private: @@ -333,7 +334,7 @@ class HipTimer : public Timer { GKO_ASSERT_NO_HIP_ERRORS(hipEventRecord(start_)); } - std::int64_t toc_impl() override + double toc_impl() override { gko::hip::device_guard g{id_}; // Currently, gko::HipExecutor always use default stream. @@ -344,7 +345,8 @@ class HipTimer : public Timer { // resolution of around 0.5 microseconds GKO_ASSERT_NO_HIP_ERRORS( hipEventElapsedTime(&duration_time, start_, stop_)); - return static_cast(duration_time * 1e6); + constexpr int sec_in_ms = 1e3; + return static_cast(duration_time) / sec_in_ms; } private: