1 // Copyright 2016-2021 Francesco Biscani (bluescarni@gmail.com)
2 //
3 // This file is part of the mp++ library.
4 //
5 // This Source Code Form is subject to the terms of the Mozilla
6 // Public License v. 2.0. If a copy of the MPL was not distributed
7 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
9 #include <algorithm>
10 #include <chrono>
11 #include <fstream>
12 #include <ios>
13 #include <iostream>
14 #include <string>
15
16 #include <boost/filesystem/path.hpp>
17
18 #include <fmt/core.h>
19
20 #include "utils.hpp"
21
22 namespace mppp_benchmark
23 {
24
simple_timer()25 simple_timer::simple_timer() : m_start(std::chrono::high_resolution_clock::now()) {}
26
elapsed() const27 double simple_timer::elapsed() const
28 {
29 return static_cast<double>(
30 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - m_start)
31 .count());
32 }
33
warmup()34 void warmup()
35 {
36 fmt::print("Warming up");
37 for (auto volatile counter = 0ull; counter < 1000000000ull; ++counter) {
38 if (counter % 100000000ull == 0u) {
39 fmt::print(".");
40 std::cout.flush();
41 }
42 }
43 fmt::print(" Done\n");
44 }
45
46 namespace detail
47 {
48
filename_from_abs_path(const std::string & s)49 std::string filename_from_abs_path(const std::string &s)
50 {
51 return boost::filesystem::path(s).stem().string();
52 }
53
54 } // namespace detail
55
56 const char *res_print_format = "{:16}: {:>5.0f}ms, res = {}\n";
57
58 namespace detail
59 {
60
61 namespace
62 {
63
64 constexpr auto py_script = R"(data = {0}
65
66 if __name__ == '__main__':
67 import matplotlib as mpl
68 import matplotlib.pyplot as plt
69
70 mpl.use('Agg')
71
72 plt.style.use('seaborn')
73
74 x_pos = list(range(len(data)))
75 labels, height = map(list, zip(*data))
76
77 plt.barh(x_pos, height)
78 plt.yticks(x_pos, labels)
79 plt.title('{1}')
80 plt.xlabel('Time (ms)')
81 for i, v in enumerate(height):
82 plt.text(v, i, " "+str(v), va='center', fontweight='bold')
83 plt.tight_layout()
84
85 plt.savefig('{1}.png', bbox_inches='tight', dpi=250)
86 )";
87
88 }
89
90 } // namespace detail
91
write_out(data_t bdata,const std::string & benchmark_name)92 void write_out(data_t bdata, const std::string &benchmark_name)
93 {
94 // Order the benchmark data according to performance.
95 using rec_t = data_t::value_type;
96 std::sort(bdata.begin(), bdata.end(), [](const rec_t &p1, const rec_t &p2) { return p1.second > p2.second; });
97
98 // Create the Python list with the result data.
99 std::string py_data_list = "[";
100 for (const auto &p : bdata) {
101 py_data_list += fmt::format("('{}', {:.0f}), ", p.first, p.second);
102 }
103 py_data_list += "]";
104
105 // Write out the Python script.
106 std::ofstream of(benchmark_name + ".py", std::ios_base::trunc);
107 of.exceptions(std::ios_base::failbit);
108 of << fmt::format(detail::py_script, py_data_list, benchmark_name);
109 }
110
111 } // namespace mppp_benchmark
112