Почему преобразование строки в число происходит так медленно в C++?

Эта функция читает массив двойников из строки:

vector<double> parseVals(string& str) {
    stringstream ss(str);
    vector<double> vals;
    double val;
    while (ss >> val) vals.push_back(val);
    return vals;
}

При вызове строки, содержащей 1 миллион чисел, функции требуется 7,8 секунды для выполнения (Core i5, 3,3 ГГц ). Это означает, что на разбор ОДНОГО ЧИСЛА тратится 25000 циклов ЦП.

пользователь 315052 указал, что тот же самый код работает на порядок быстрее в его системе,и дальнейшее тестирование показало очень большие различия в производительности между различными системами и компиляторами (, также см. ответ пользователя 315052):

1. Win7, Visual Studio 2012RC or Intel C++ 2013 beta: 7.8  sec
2. Win7, mingw / g++ 4.5.2                          : 4    sec
3. Win7, Visual Studio 2010                         : 0.94 sec
4. Ubuntu 12.04, g++ 4.7                            : 0.65 sec

Я нашел отличную альтернативу в библиотеке Boost/Spirit. Код безопасный, лаконичный и очень быстрый (0,06 секунды на VC2012, в 130 раз быстрее, чем stringstream ).

#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

vector<double> parseVals4(string& str) {
    vector<double> vals;
    qi::phrase_parse(str.begin(), str.end(),
        *qi::double_ >> qi::eoi, ascii::space, vals);
    return vals;
}

Хотя это решает проблему с практической точки зрения, я все же хотел бы знать, почему производительность stringstream настолько непостоянна. Я профилировал программу, чтобы определить узкое место, но код STL мне кажется тарабарщиной. Будем очень признательны за комментарии от всех, кто знаком с внутренним устройством STL.

PS :Оптимизация составляет O2 или лучше во всех вышеуказанных таймингах. Ни создание stringstream, ни перераспределение векторной фигуры в профиле программы. Практически все время оператор добычи проводит внутри.

6
задан 13 revs 13 July 2012 в 07:33
поделиться