| // generate_table.cpp |
| // |
| // Copyright (c) 2009 |
| // Steven Watanabe |
| // |
| // Distributed under the Boost Software License, Version 1.0. (See |
| // accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| |
| #include <vector> |
| #include <utility> |
| #include <iostream> |
| #include <cstring> |
| #include <fstream> |
| #include <boost/regex.hpp> |
| #include <boost/tuple/tuple.hpp> |
| #include <boost/lexical_cast.hpp> |
| #include <boost/foreach.hpp> |
| #include <boost/format.hpp> |
| #include <boost/multi_index_container.hpp> |
| #include <boost/multi_index/hashed_index.hpp> |
| #include <boost/multi_index/sequenced_index.hpp> |
| |
| boost::regex generator_regex("(?:fixed-range )?([^:]+): (\\d+(?:\\.\\d+)?) nsec/loop = \\d+(?:\\.\\d+)? CPU cycles"); |
| boost::regex distribution_regex("([^\\s]+)( virtual function)? ([^:]+): (\\d+(?:\\.\\d+)?) nsec/loop = \\d+(?:\\.\\d+)? CPU cycles"); |
| |
| std::string template_name(std::string arg) { |
| return boost::regex_replace(arg, boost::regex("[^\\w]"), "_"); |
| } |
| |
| struct compare_second { |
| template<class Pair> |
| bool operator()(const Pair& p1, const Pair& p2) const { |
| return (p1.second < p2.second); |
| } |
| }; |
| |
| typedef boost::multi_index_container< |
| std::string, |
| boost::mpl::vector< |
| boost::multi_index::sequenced<>, |
| boost::multi_index::hashed_unique<boost::multi_index::identity<std::string> > |
| > |
| > unique_list; |
| |
| int main() { |
| std::vector<std::pair<std::string, double> > generator_info; |
| std::string line; |
| while(std::getline(std::cin, line)) { |
| boost::smatch match; |
| if(std::strncmp(line.c_str(), "counting ", 9) == 0) break; |
| if(boost::regex_match(line, match, generator_regex)) { |
| std::string generator(match[1]); |
| double time = boost::lexical_cast<double>(match[2]); |
| if(generator != "counting") { |
| generator_info.push_back(std::make_pair(generator, time)); |
| } |
| } else { |
| std::cerr << "oops: " << line << std::endl; |
| } |
| } |
| |
| double min = std::min_element(generator_info.begin(), generator_info.end(), compare_second())->second; |
| |
| std::ofstream generator_defs("performance_data.qbk"); |
| std::ofstream generator_performance("generator_performance.qbk"); |
| generator_performance << "[table Basic Generators\n"; |
| generator_performance << " [[generator] [M rn/sec] [time per random number \\[nsec\\]] " |
| "[relative speed compared to fastest \\[percent\\]]]\n"; |
| |
| typedef std::pair<std::string, double> pair_type; |
| BOOST_FOREACH(const pair_type& pair, generator_info) { |
| generator_defs << boost::format("[template %s_speed[] %d%%]\n") |
| % template_name(pair.first) % static_cast<int>(100*min/pair.second); |
| generator_performance << boost::format(" [[%s][%g][%g][%d%%]]\n") |
| % pair.first % (1000/pair.second) % pair.second % static_cast<int>(100*min/pair.second); |
| } |
| generator_performance << "]\n"; |
| |
| std::map<std::pair<std::string, std::string>, double> distribution_info; |
| unique_list generator_names; |
| unique_list distribution_names; |
| do { |
| boost::smatch match; |
| if(boost::regex_match(line, match, distribution_regex)) { |
| if(!match[2].matched && match[1] != "counting") { |
| std::string generator(match[1]); |
| std::string distribution(match[3]); |
| double time = boost::lexical_cast<double>(match[4]); |
| generator_names.push_back(generator); |
| distribution_names.push_back(distribution); |
| distribution_info.insert(std::make_pair(std::make_pair(distribution, generator), time)); |
| } |
| } else { |
| std::cerr << "oops: " << line << std::endl; |
| } |
| } while(std::getline(std::cin, line)); |
| |
| std::ofstream distribution_performance("distribution_performance.qbk"); |
| |
| distribution_performance << "[table Distributions\n"; |
| distribution_performance << " [[\\[M rn/sec\\]]"; |
| BOOST_FOREACH(const std::string& generator, generator_names) { |
| distribution_performance << boost::format("[%s]") % generator; |
| } |
| distribution_performance << "]\n"; |
| BOOST_FOREACH(const std::string& distribution, distribution_names) { |
| distribution_performance << boost::format(" [[%s]") % distribution; |
| BOOST_FOREACH(const std::string& generator, generator_names) { |
| std::map<std::pair<std::string, std::string>, double>::iterator pos = |
| distribution_info.find(std::make_pair(distribution, generator)); |
| if(pos != distribution_info.end()) { |
| distribution_performance << boost::format("[%g]") % (1000/pos->second); |
| } else { |
| distribution_performance << "[-]"; |
| } |
| } |
| distribution_performance << "]\n"; |
| } |
| distribution_performance << "]\n"; |
| } |