• c++ stod很慢


    C++ Convert String to Double Speed

    (There is also a string-to-int performance test.)

    A performance benchmark of which method is faster of converting an std::string to a double. The goal is ending up with a double of the value represented in an std::string.

    The tested methods are:

    Source for the test is at speed-string-to-double.cpp with cycle.h.

    The compilers are Microsoft Visual C++ 2010 with _SECURE_SCL disabled, GNU g++ 4.6.0, and LLVM clang++ from Arch.


    Tests were run for converting 100000 string containing doubles in the range +/- 99999.99999. The result for the naive loop and atof() are set as the baseline 100% and the other numbers is time spent relative to those. The naive loop wins by a large margin, but Boost.Spirit is the fastest correct implementation.

    Windows: MSVC++ 2010

    • Compiler: MSVC++ 2010 _SECURE_SCL=0
    • Arch: Windows 7 64 bit, 1.60GHz Core i7 Q720, 8 GiB RAM
    VC++ 2010TicksRelative to naiveRelative to atof()
    naive 4366220 1.00 0.05
    atof() 82732774 18.95 1.00
    strtod() 83189198 19.05 1.01
    sscanf() 168568387 38.61 2.04
    spirit qi 18932917 4.34 0.23
    lexical_cast 332374407 76.12 4.02
    stringstream 361943816 82.90 4.37
    stringstream reused 240848392 55.16 2.91

    Linux: GNU g++ 4.6.0

    • Compiler: GNU g++ 4.6.0 -O3
    • Arch: VirtualBox on the Windows machine, VT-x, Arch Linux, kernel 2.6.38-ARCH, 1 GiB RAM
    g++ 4.6.0TicksRelative to naiveRelative to atof()
    naive 4656159 1.00 0.15
    atof() 30605490 6.57 1.00
    strtod() 30963926 6.65 1.01
    sscanf() 56235197 12.08 1.84
    spirit qi 20731062 4.45 0.68
    lexical_cast 139521406 29.96 4.56
    stringstream 184723298 39.67 6.04
    stringstream reused 100905407 21.67 3.30

    Linux: LLVM clang++ 2.9

    • Compiler: clang++ 2.9 -O3
    • Arch: VirtualBox on the Windows machine, VT-x, Arch Linux, kernel 2.6.38-ARCH, 1 GiB RAM
    clang++ 2.9TicksRelative to naiveRelative to atof()
    naive 6804881 1.00 0.22
    atof() 30829865 4.53 1.00
    strtod() 30871514 4.54 1.00
    sscanf() 57903993 8.51 1.88
    spirit qi 24411041 3.59 0.79
    lexical_cast 149339833 21.95 4.84
    stringstream 191239066 28.10 6.20
    stringstream reused 100461405 14.76 3.26
     
     
    #ifdef _MSC_VER
        #define _SECURE_SCL 0
        #define _CRT_SECURE_NO_DEPRECATE 1
        #define WIN32_LEAN_AND_MEAN
        #define VC_EXTRALEAN
        #define NOMINMAX
    #endif
    
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <ctime>
    #include <cmath>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <iomanip>
    #include <sstream>
    #include <boost/lexical_cast.hpp>
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix_core.hpp>
    #include <boost/spirit/include/phoenix_operator.hpp>
    #include "cycle.h"
    
    static const size_t N = 100000;
    static const size_t R = 7;
    
    void PrintStats(std::vector<double> timings) {
        double fastest = std::numeric_limits<double>::max();
    
        std::cout << std::fixed << std::setprecision(2);
        std::cout << "[";
        for (size_t i = 1 ; i<timings.size()-1 ; ++i) {
            fastest = std::min(fastest, timings[i]);
            std::cout << timings[i] << ",";
        }
        std::cout << timings.back();
        std::cout << "]";
    
        double sum = 0.0;
        for (size_t i = 1 ; i<timings.size() ; ++i) {
            sum += timings[i];
        }
        double avg = sum / static_cast<double>(timings.size()-1);
    
        sum = 0.0;
        for (size_t i = 1 ; i<timings.size() ; ++i) {
            timings[i] = pow(timings[i]-avg, 2);
            sum += timings[i];
        }
        double var = sum/(timings.size()-2);
        double sdv = sqrt(var);
    
        std::cout << " with fastest " << fastest << ", average " << avg << ", stddev " << sdv;
    }
    
    double naive(const char *p) {
        double r = 0.0;
        bool neg = false;
        if (*p == '-') {
            neg = true;
            ++p;
        }
        while (*p >= '0' && *p <= '9') {
            r = (r*10.0) + (*p - '0');
            ++p;
        }
        if (*p == '.') {
            double f = 0.0;
            int n = 0;
            ++p;
            while (*p >= '0' && *p <= '9') {
                f = (f*10.0) + (*p - '0');
                ++p;
                ++n;
            }
            r += f / std::pow(10.0, n);
        }
        if (neg) {
            r = -r;
        }
        return r;
    }
    
    int main() {
        std::vector<std::string> nums;
        nums.reserve(N);
        for (size_t i=0 ; i<N ; ++i) {
            std::string y;
            if (i & 1) {
                y += '-';
            }
            y += boost::lexical_cast<std::string>(i);
            y += '.';
            y += boost::lexical_cast<std::string>(i);
            nums.push_back(y);
        }
    
        {
            double tsum = 0.0;
            std::vector<double> timings;
            timings.reserve(R);
            for (size_t r=0 ; r<R ; ++r) {
                ticks start = getticks();
                for (size_t i=0 ; i<nums.size() ; ++i) {
                    double x = naive(nums[i].c_str());
                    tsum += x;
                }
                ticks end = getticks();
                double timed = elapsed(end, start);
                timings.push_back(timed);
            }
    
            std::cout << "naive: ";
            PrintStats(timings);
            std::cout << std::endl;
            std::cout << tsum << std::endl;
        }
    
        {
            double tsum = 0.0;
            std::vector<double> timings;
            timings.reserve(R);
            for (size_t r=0 ; r<R ; ++r) {
                ticks start = getticks();
                for (size_t i=0 ; i<nums.size() ; ++i) {
                    double x = atof(nums[i].c_str());
                    tsum += x;
                }
                ticks end = getticks();
                double timed = elapsed(end, start);
                timings.push_back(timed);
            }
    
            std::cout << "atof(): ";
            PrintStats(timings);
            std::cout << std::endl;
            std::cout << tsum << std::endl;
        }
    
        {
            double tsum = 0.0;
            std::vector<double> timings;
            timings.reserve(R);
            for (size_t r=0 ; r<R ; ++r) {
                ticks start = getticks();
                for (size_t i=0 ; i<nums.size() ; ++i) {
                    double x = strtod(nums[i].c_str(), 0);
                    tsum += x;
                }
                ticks end = getticks();
                double timed = elapsed(end, start);
                timings.push_back(timed);
            }
    
            std::cout << "strtod(): ";
            PrintStats(timings);
            std::cout << std::endl;
            std::cout << tsum << std::endl;
        }
    
        {
            double tsum = 0.0;
            std::vector<double> timings;
            timings.reserve(R);
            for (size_t r=0 ; r<R ; ++r) {
                ticks start = getticks();
                for (size_t i=0 ; i<nums.size() ; ++i) {
                    double x = 0.0;
                    sscanf(nums[i].c_str(), "%lf", &x);
                    tsum += x;
                }
                ticks end = getticks();
                double timed = elapsed(end, start);
                timings.push_back(timed);
            }
    
            std::cout << "sscanf(): ";
            PrintStats(timings);
            std::cout << std::endl;
            std::cout << tsum << std::endl;
        }
    
        {
            double tsum = 0.0;
            std::vector<double> timings;
            timings.reserve(R);
            for (size_t r=0 ; r<R ; ++r) {
                ticks start = getticks();
                for (size_t i=0 ; i<nums.size() ; ++i) {
                    double x = boost::lexical_cast<double>(nums[i]);
                    tsum += x;
                }
                ticks end = getticks();
                double timed = elapsed(end, start);
                timings.push_back(timed);
            }
    
            std::cout << "lexical_cast: ";
            PrintStats(timings);
            std::cout << std::endl;
            std::cout << tsum << std::endl;
        }
    
        {
            using boost::spirit::qi::double_;
            using boost::spirit::qi::parse;
            double tsum = 0.0;
            std::vector<double> timings;
            timings.reserve(R);
            for (size_t r=0 ; r<R ; ++r) {
                ticks start = getticks();
                for (size_t i=0 ; i<nums.size() ; ++i) {
                    double x = 0.0;
                    char const *str = nums[i].c_str();
                    parse(str, &str[nums[i].size()], double_, x);
                    tsum += x;
                }
                ticks end = getticks();
                double timed = elapsed(end, start);
                timings.push_back(timed);
            }
    
            std::cout << "spirit qi: ";
            PrintStats(timings);
            std::cout << std::endl;
            std::cout << tsum << std::endl;
        }
    
        {
            double tsum = 0.0;
            std::vector<double> timings;
            timings.reserve(R);
            for (size_t r=0 ; r<R ; ++r) {
                ticks start = getticks();
                for (size_t i=0 ; i<nums.size() ; ++i) {
                    std::istringstream ss(nums[i]);
                    double x = 0.0;
                    ss >> x;
                    tsum += x;
                }
                ticks end = getticks();
                double timed = elapsed(end, start);
                timings.push_back(timed);
            }
    
            std::cout << "stringstream: ";
            PrintStats(timings);
            std::cout << std::endl;
            std::cout << tsum << std::endl;
        }
    
        {
            double tsum = 0.0;
            std::vector<double> timings;
            timings.reserve(R);
            for (size_t r=0 ; r<R ; ++r) {
                ticks start = getticks();
                std::istringstream ss;
                for (size_t i=0 ; i<nums.size() ; ++i) {
                    ss.str(nums[i]);
                    ss.clear();
                    double x = 0.0;
                    ss >> x;
                    tsum += x;
                }
                ticks end = getticks();
                double timed = elapsed(end, start);
                timings.push_back(timed);
            }
    
            std::cout << "stringstream reused: ";
            PrintStats(timings);
            std::cout << std::endl;
            std::cout << tsum << std::endl;
        }
    }
    View Code
  • 相关阅读:
    CSS3选择器之:nth-child(n)
    【转】JS中,中国标准时间转化为yyyy-MM-dd
    【转】浅谈JavaScript中forEach与each
    Can't connect to MySQL server (10060)
    Linux/CentOS下安装MySql RPM Bundle
    查看CentOS/Linux的版本信息
    Java中IO流,输入输出流概述与总结
    阿里历年经典Java面试题汇总
    架构师眼中的高并发架构
    Java面试经
  • 原文地址:https://www.cnblogs.com/xpvincent/p/7599757.html
Copyright © 2020-2023  润新知