Last active
January 7, 2021 23:19
-
-
Save linsinan1995/c4a96bfc1da91cb61847995c5697a274 to your computer and use it in GitHub Desktop.
easy benchmark template and example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// simple framework for timing, feel free to modify it. | |
#include <chrono> | |
#include <thread> | |
#include <iostream> | |
template <typename Type = std::chrono::milliseconds> class Timer; | |
template <typename Type = std::chrono::milliseconds> class scope_timer; | |
using timer_sec_t = Timer<std::chrono::seconds>; | |
using timer_min_t = Timer<std::chrono::minutes>; | |
using timer_nano_t = Timer<std::chrono::nanoseconds>; | |
using timer_micro_t = Timer<std::chrono::microseconds>; | |
using timer_milli_t = Timer<std::chrono::milliseconds>; | |
template <typename Type> | |
class Timer { | |
std::chrono::time_point<std::chrono::high_resolution_clock> _start, _end; | |
public: | |
size_t niter = 1; | |
size_t total = 0; | |
std::string name; | |
std::ostream &m_os; | |
Timer(std::string name, std::ostream &os = std::cout ) : | |
name(move(name)), | |
m_os(os) | |
{} | |
Timer(std::string name, size_t iter, std::ostream &os = std::cout ) : | |
name(move(name)), | |
niter(iter), | |
m_os(os) | |
{} | |
void start() { | |
_start = std::chrono::high_resolution_clock::now(); | |
} | |
void stop() { | |
_end = std::chrono::high_resolution_clock::now(); | |
total = std::chrono::duration_cast<Type>( _end - _start ).count(); | |
} | |
void show() { | |
m_os << "Job <" << name << ">" << " tooks " << (total / niter); | |
if constexpr (std::is_same<Type, std::chrono::milliseconds>::value != 0) | |
m_os << " milliseconds to finish!" << std::endl; | |
else if constexpr (std::is_same<Type, std::chrono::microseconds>::value != 0) | |
m_os << " microseconds to finish!" << std::endl; | |
else if constexpr (std::is_same<Type, std::chrono::seconds>::value != 0) | |
m_os << " seconds to finish!" << std::endl; | |
else if constexpr (std::is_same<Type, std::chrono::nanoseconds>::value != 0) | |
m_os << " nanoseconds to finish!" << std::endl; | |
else if constexpr (std::is_same<Type, std::chrono::minutes>::value != 0) | |
m_os << " minutes to finish!" << std::endl; | |
} | |
}; | |
template <typename Type> | |
class scope_timer { | |
Timer<Type> _t; | |
public: | |
template <typename ...Args> | |
scope_timer(Args &&...args) : _t(std::forward<Args...> (args...) ) { _t.start(); } | |
~scope_timer() { _t.stop(); _t.show(); } | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// use case | |
#include <thread> | |
#include <vector> | |
#include <functional> | |
#include <numeric> | |
#include <algorithm> | |
#include <cassert> | |
#include "benchmark.h" | |
using namespace std; | |
using namespace chrono; | |
using namespace std::chrono_literals; // c++ 14 | |
inline void compute(vector<int> &v, int l, int r) { | |
while (l < r) { v[l] = l; l ++; } | |
} | |
void p_iota(vector<int> &v, int l , int r, int ncore) { | |
vector<thread> thread_lists; | |
int n = r / ncore; | |
for (int i = 0; i < ncore; i ++) { | |
if (i == ncore - 1) thread_lists.push_back(thread(compute, ref(v), i * n, r)); | |
else thread_lists.push_back(thread(compute, ref(v), i * n, (i + 1) * n)); | |
} | |
for_each(thread_lists.begin(), thread_lists.end(), mem_fn(&thread::join)); | |
} | |
// using timer_micro = Timer<microseconds>; | |
int main () { | |
vector<int> test_cases { 100000, 1000000, 10000000, 100000000 }; | |
// or | |
// instead of scope_timer, you can directly use Timer class, but you | |
// need manually call member function Timer::stop(). | |
cout << "=======================loop=====================\n" << flush; | |
for (auto n : test_cases) { | |
vector<int> v (n); | |
scope_timer t("loop-" + to_string(n)); | |
for (int i = 0; i < n; i++) { v[i] = i; } | |
} | |
cout << "\n=====================std::iota==================\n" << flush; | |
for (auto n : test_cases) { | |
vector<int> v (n); | |
scope_timer t("iota-" + to_string(n)); | |
iota(v.begin(), v.end(), 0); | |
} | |
cout << "\n=====================p_iota==================\n" << flush; | |
for (auto n : test_cases) { | |
vector<int> v (n); | |
scope_timer t("p_iota-" + to_string(n)); | |
p_iota(v, 0, n, thread::hardware_concurrency()); | |
} | |
cout << "\n===================valid test==================\n" << flush; | |
for (auto n : test_cases) { | |
vector<int> v (n), v1(n), v2(n); | |
// assign | |
p_iota(v, 0, n, thread::hardware_concurrency()); | |
iota(v1.begin(), v1.end(), 0); | |
for (int i = 0; i < n; i++) { v2[i] = i; } | |
// assign end | |
for (int i = 0; i < n; i++ ) { assert( v[i] == v1[i] && v1[i] == v2[i] ); } | |
} | |
cout << "Valid test passed!\n" << flush; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# read filename | |
filename=p_iota.cpp | |
g++ -std=c++17 -O2 $filename -fext-numeric-literals -pthread -o test | |
./test | |
rm test |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment