• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // generate_table.cpp
2 //
3 // Copyright (c) 2009
4 // Steven Watanabe
5 //
6 // Distributed under the Boost Software License, Version 1.0. (See
7 // accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9 
10 #include <vector>
11 #include <utility>
12 #include <iostream>
13 #include <cstring>
14 #include <fstream>
15 #include <boost/regex.hpp>
16 #include <boost/tuple/tuple.hpp>
17 #include <boost/lexical_cast.hpp>
18 #include <boost/foreach.hpp>
19 #include <boost/format.hpp>
20 #include <boost/multi_index_container.hpp>
21 #include <boost/multi_index/hashed_index.hpp>
22 #include <boost/multi_index/sequenced_index.hpp>
23 
24 boost::regex generator_regex("(?:fixed-range )?([^:]+): (\\d+(?:\\.\\d+)?) nsec/loop = \\d+(?:\\.\\d+)? CPU cycles");
25 boost::regex distribution_regex("([^\\s]+)( virtual function)? ([^:]+): (\\d+(?:\\.\\d+)?) nsec/loop = \\d+(?:\\.\\d+)? CPU cycles");
26 
template_name(std::string arg)27 std::string template_name(std::string arg) {
28     return boost::regex_replace(arg, boost::regex("[^\\w]"), "_");
29 }
30 
31 struct compare_second {
32     template<class Pair>
operator ()compare_second33     bool operator()(const Pair& p1, const Pair& p2) const {
34         return (p1.second < p2.second);
35     }
36 };
37 
38 typedef boost::multi_index_container<
39     std::string,
40     boost::mpl::vector<
41         boost::multi_index::sequenced<>,
42         boost::multi_index::hashed_unique<boost::multi_index::identity<std::string> >
43     >
44 > unique_list;
45 
main(int argc,char ** argv)46 int main(int argc, char** argv) {
47 
48     std::string suffix;
49     std::string id;
50 
51     if(argc >= 2 && std::strcmp(argv[1], "-linux") == 0) {
52         suffix = "linux";
53         id = "Linux";
54     } else  {
55         suffix = "windows";
56         id = "Windows";
57     }
58 
59     std::vector<std::pair<std::string, double> > generator_info;
60     std::string line;
61     while(std::getline(std::cin, line)) {
62         boost::smatch match;
63         if(std::strncmp(line.c_str(), "counting ", 9) == 0) break;
64         if(boost::regex_match(line, match, generator_regex)) {
65             std::string generator(match[1]);
66             double time = boost::lexical_cast<double>(match[2]);
67             if(generator != "counting") {
68                 generator_info.push_back(std::make_pair(generator, time));
69             }
70         } else {
71             std::cerr << "oops: " << line << std::endl;
72         }
73     }
74 
75     double min = std::min_element(generator_info.begin(), generator_info.end(), compare_second())->second;
76 
77     std::ofstream generator_defs("performance_data.qbk");
78     std::ofstream generator_performance(("generator_performance_" + suffix + ".qbk").c_str());
79     generator_performance << "[table Basic Generators (" << id << ")\n";
80     generator_performance << "  [[generator] [M rn/sec] [time per random number \\[nsec\\]] "
81                              "[relative speed compared to fastest \\[percent\\]]]\n";
82 
83     typedef std::pair<std::string, double> pair_type;
84     BOOST_FOREACH(const pair_type& pair, generator_info) {
85         generator_defs << boost::format("[template %s_speed[] %d%%]\n")
86             % template_name(pair.first) % static_cast<int>(100*min/pair.second);
87         generator_performance << boost::format("  [[%s][%g][%g][%d%%]]\n")
88             % pair.first % (1000/pair.second) % pair.second % static_cast<int>(100*min/pair.second);
89     }
90     generator_performance << "]\n";
91 
92     std::map<std::pair<std::string, std::string>, double> distribution_info;
93     unique_list generator_names;
94     unique_list distribution_names;
95     do {
96         boost::smatch match;
97         if(boost::regex_match(line, match, distribution_regex)) {
98             if(!match[2].matched && match[1] != "counting") {
99                 std::string generator(match[1]);
100                 std::string distribution(match[3]);
101                 double time = boost::lexical_cast<double>(match[4]);
102                 generator_names.push_back(generator);
103                 distribution_names.push_back(distribution);
104                 distribution_info.insert(std::make_pair(std::make_pair(distribution, generator), time));
105             }
106         } else {
107             std::cerr << "oops: " << line << std::endl;
108         }
109     } while(std::getline(std::cin, line));
110 
111     std::ofstream distribution_performance(("distribution_performance_" + suffix + ".qbk").c_str());
112 
113     distribution_performance << "[table Distributions (" << id << ")\n";
114     distribution_performance << "  [[\\[M rn/sec\\]]";
115     BOOST_FOREACH(const std::string& generator, generator_names) {
116         distribution_performance << boost::format("[%s]") % generator;
117     }
118     distribution_performance << "]\n";
119     BOOST_FOREACH(const std::string& distribution, distribution_names) {
120         distribution_performance << boost::format("  [[%s]") % distribution;
121         BOOST_FOREACH(const std::string& generator, generator_names) {
122             std::map<std::pair<std::string, std::string>, double>::iterator pos =
123                 distribution_info.find(std::make_pair(distribution, generator));
124             if(pos != distribution_info.end()) {
125                 distribution_performance << boost::format("[%g]") % (1000/pos->second);
126             } else {
127                 distribution_performance << "[-]";
128             }
129         }
130         distribution_performance << "]\n";
131     }
132     distribution_performance << "]\n";
133 }
134