Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > accumulate в 4 раза медленнее цикла


Автор: borisbn 29.9.2014, 18:01
Здравствуйте.
Такой код:
Код

#include <algorithm>
#include <iostream>
#include <chrono>
#include <vector>

using namespace std;

using vector_t = float;

template< class F >
void measure( const char * msg, F && f ) {
    chrono::steady_clock::time_point start = chrono::steady_clock::now();
    vector_t res = f();
    chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
    cout << msg << chrono::duration_cast<chrono::microseconds>(end - start).count() << "us. ";
    cout << "The result is " << res << endl;
}

int main() 
{
    const int n = 20000000;

    measure( "for sum took ", [n]() -> vector_t {
        vector_t sum = 0;
        vector< vector_t > vec( n, 1 );
        for ( int i = 0; i < n; ++i ) {
            sum += vec[ i ];
        }
        return sum;
    } );
    measure( "for iters sum took ", [n]() -> vector_t {
        vector_t sum = 0;
        vector< vector_t > vec( n, 1 );
        for ( auto i = vec.begin(), e = vec.end(); i != e; ++i ) {
            sum += *i;
        }
        return sum;
    } );
    measure( "for_each sum took ", [n]() -> vector_t {
        vector_t sum = 0;
        vector< vector_t > vec( n, 1 );
        for_each( vec.begin(), vec.end(), [&sum]( vector_t f ) { sum += f; } );
        return sum;
    } );
    measure( "accumulate sum took ", [n]() -> vector_t {
        vector< vector_t > vec( n, 1 );
        return accumulate( vec.begin(), vec.end(), 0 );
    } );
}

даёт такой результат:
Цитата
for sum took 57356us. The result is 2e+007
for iters sum took 57429us. The result is 2e+007
for_each sum took 57332us. The result is 2e+007
accumulate sum took 192337us. The result is 2e+007


Вопрос: почему так ? ЧЯДНТ ?
P.S. Компилятор MinGW 4.8.0.
Параметры запуска:
Цитата
g++ a.cpp -std=c++11 -O2


P.P.S. Пробовал менять местами тесты - результат не меняется.

Добавлено через 4 минуты и 42 секунды
P.P.P.S. Заглянул в исходники MinGW (файл c:\mingw\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\stl_numeric.h). Там реализация до противного простая
Код

  template<typename _InputIterator, typename _Tp>
    inline _Tp
    accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
    {
      // concept requirements
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
      __glibcxx_requires_valid_range(__first, __last);

      for (; __first != __last; ++__first)
    __init = __init + *__first;
      return __init;
    }

Автор: sQu1rr 29.9.2014, 21:11
Цитата(borisbn @  29.9.2014,  18:01 Найти цитируемый пост)
return accumulate( vec.begin(), vec.end(), 0 );

Код

return accumulate( vec.begin(), vec.end(), 0.0f );

?

Добавлено через 2 минуты и 23 секунды
Насколько понимаю такая разница изза конвертации всех float в int

Автор: borisbn 29.9.2014, 22:06
sQu1rr, ты гений. Да. Так оно и есть Спасибо.

Автор: sQu1rr 30.9.2014, 00:50
Цитата(borisbn @  29.9.2014,  22:06 Найти цитируемый пост)
sQu1rr, ты гений. Да. Так оно и есть Спасибо. 

всегда можно пивом вернуть ;)

Автор: borisbn 30.9.2014, 09:03
Цитата(sQu1rr @  29.9.2014,  21:11 Найти цитируемый пост)
Насколько понимаю такая разница изза конвертации всех float в int 

Ага. Оно ещё и работало неправильно. Если создать вектор не из единиц, а из 0.5, то результат будет 0.

Цитата(sQu1rr @  30.9.2014,  00:50 Найти цитируемый пост)
всегда можно пивом вернуть ;) 

Как буду в
user posted image
обязательно верну ;)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)