timer.hpp 4.26 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
/*
 * Copyright (c) 2017 UChicago Argonne, LLC
 *
 * See COPYRIGHT in top-level directory.
 */

#ifndef __THALLIUM_TIMER_HPP
#define __THALLIUM_TIMER_HPP

#include <abt.h>
#include <thallium/exception.hpp>
#include <thallium/abt_errors.hpp>

namespace thallium {

/**
 * Exception class thrown by the timer class.
 */
class timer_exception : public exception {

    public:

    template<typename ... Args>
    timer_exception(Args&&... args)
    : exception(std::forward<Args>(args)...) {}
};

#define TL_TIMER_EXCEPTION(__fun,__ret) \
    timer_exception(#__fun," returned ", abt_error_get_name(__ret),\
            " (", abt_error_get_description(__ret),") in ",__FILE__,":",__LINE__);

#define TL_TIMER_ASSERT(__call) {\
    int __ret = __call; \
    if(__ret != ABT_SUCCESS) {\
        throw TL_TIMER_EXCEPTION(__call, __ret);\
    }\
}

/**
 * @brief Wrapper for Argobots' ABT_timer.
 */
class timer {

44 45 46
    ABT_timer m_timer;

    public:
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195

    /**
     * @brief Native handle type.
     */
    typedef ABT_timer native_handle_type;

    /**
     * @brief Get elapsed wall clock time.
     *
     * @return elapsed wall clock time.
     */
    static double wtime() {
        return ABT_get_wtime();
    }

    /**
     * @brief Return the overhead of the timer class.
     *
     * @return the overhead time when measuring the elapsed 
     * time with the timer class. It computes the time difference
     * in consecutive calls of timer::start() and timer::stop().
     * The resolution of overhead time is at least a unit of microsecond.
     */
    static double overhead() {
        timer t;
        int i;
        const int iter = 5000;
        double secs, sum = 0.0;
        for (i = 0; i < iter; i++) {
            t.start();
            t.stop();
            secs = t.read();
            sum += secs;
        }
        return sum/iter;
    }

    /**
     * @brief Get the native handle.
     *
     * @return the native handle.
     */
    native_handle_type native_handle() const {
        return m_timer;
    }

    /**
     * @brief Constructor.
     */
    timer() {
        TL_TIMER_ASSERT(ABT_timer_create(&m_timer));
    }

    /**
     * @brief Destructor.
     */
    ~timer() {
        ABT_timer_free(&m_timer);
    }

    /**
     * @brief Copy constructor.
     */
    timer(const timer& other) 
    : m_timer(ABT_TIMER_NULL) {
        if(other.m_timer != ABT_TIMER_NULL) {
            TL_TIMER_ASSERT(ABT_timer_dup(other.m_timer, &m_timer));
        }
    }

    /**
     * @brief Move constructor.
     */
    timer(timer&& other)
    : m_timer(other.m_timer) {
        other.m_timer = ABT_TIMER_NULL;
    }

    /**
     * @brief Copy-assignment operator.
     */
    timer& operator=(const timer& other) {
        if(this == &other) return *this;
        if(m_timer != ABT_TIMER_NULL) {
             TL_TIMER_ASSERT(ABT_timer_free(&m_timer));
             m_timer = ABT_TIMER_NULL;
        }
        if(other.m_timer != ABT_TIMER_NULL) {
            TL_TIMER_ASSERT(ABT_timer_dup(other.m_timer, &m_timer));
        }
        return *this;
    }

    /**
     * @brief Move-assignment operator.
     */
    timer& operator=(timer&& other) {
        if(this == &other) return *this;
        if(m_timer != ABT_TIMER_NULL) {
            TL_TIMER_ASSERT(ABT_timer_free(&m_timer));
            m_timer = ABT_TIMER_NULL;
        }
        m_timer = other.m_timer;
        other.m_timer = ABT_TIMER_NULL;
        return *this;
    }

    /**
     * @brief Starts the timer.
     */
    void start() {
        TL_TIMER_ASSERT(ABT_timer_start(m_timer));
    }

    /**
     * @brief Stops the timer.
     */
    void stop() {
        TL_TIMER_ASSERT(ABT_timer_stop(m_timer));
    }

    /**
     * @brief Reads the current value of the timer.
     * Returns the time difference in seconds between
     * the start time of timer (when timer::start() was called)
     * and the end time of timer (when timer::stop() was called).
     * 
     * The resolution of elapsed time is at least a unit of microsecond.
     */
    double read() const {
        double t;
        TL_TIMER_ASSERT(ABT_timer_read(m_timer, &t));
        return t;
    }

    /**
     * @see timer::read
     */
    explicit operator double() const {
        return read();
    }
};

}

#undef TL_TIMER_EXCEPTION
#undef TL_TIMER_ASSERT

#endif /* end of include guard */