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