Back to TILs

# C++ reduce ``````  vector<int> vec{ 0, 1, 2, 3, 4, 5 };

auto sum0 = accumulate( begin( vec ), end( vec ), 0.0 );        // sequential
auto sum1 = reduce( begin( vec ), end( vec ) );                 // sequential
auto sum2 = reduce( execution::seq, begin( vec ), end( vec ) ); // sequential
auto sum3 = reduce( execution::par, begin( vec ), end( vec ) ); // parallel
cout << "Sum: " << sum0 << " " << sum1 << " " << sum2 << " " << sum3 << '\n';
``````

## Performance

The average time to operate over 10M items normalized by the `accumulate` time is:

• `accumulate`: 100%
• `reduce par`: 37%
• `reduce seq`: 165%

Though `std::reduce` seems faster compared to `std::accumulate`, you should be careful when using it with non-commutative binary operations.

``````  const vector<double> v( 10'000'007, 0.5 );
map<string, double>  means;

cout << fixed << setprecision( 1 );
const int N = 5;
for( auto i = 0; i < N; ++i ) {
{
const auto                            t1     = chrono::high_resolution_clock::now();
const double                          result = accumulate( v.cbegin(), v.cend(), 0.0 );
const auto                            t2     = chrono::high_resolution_clock::now();
const chrono::duration<double, milli> ms     = t2 - t1;
cout << "std::accumulate result " << result << " took " << ms.count() << " ms\n";
means["accumulate"] += ms.count() / N;
}

{
const auto                            t1     = chrono::high_resolution_clock::now();
const double                          result = reduce( execution::seq, v.cbegin(), v.cend() );
const auto                            t2     = chrono::high_resolution_clock::now();
const chrono::duration<double, milli> ms     = t2 - t1;
cout << "std::reduce seq result " << result << " took " << ms.count() << " ms\n";
means["reduce seq"] += ms.count() / N;
}

{
const auto                            t1     = chrono::high_resolution_clock::now();
const double                          result = reduce( execution::par, v.cbegin(), v.cend() );
const auto                            t2     = chrono::high_resolution_clock::now();
const chrono::duration<double, milli> ms     = t2 - t1;
cout << "std::reduce par result " << result << " took " << ms.count() << " ms\n";
means["reduce par"] += ms.count() / N;
}
}

cout << "Average time to operate over 10M items:\n";
for( const auto &[key, value] : means ) {
cout << key << ": " << value << "ms\n";
}
``````

## Possible output

``````Sum: 15 15 15 15
std::accumulate result 5000003.5 took 92.0 ms
std::reduce seq result 5000003.5 took 118.1 ms
std::reduce par result 5000003.5 took 24.7 ms
std::accumulate result 5000003.5 took 75.9 ms
std::reduce seq result 5000003.5 took 117.2 ms
std::reduce par result 5000003.5 took 24.7 ms
std::accumulate result 5000003.5 took 77.0 ms
std::reduce seq result 5000003.5 took 117.8 ms
std::reduce par result 5000003.5 took 44.2 ms
std::accumulate result 5000003.5 took 78.9 ms
std::reduce seq result 5000003.5 took 117.3 ms
std::reduce par result 5000003.5 took 24.7 ms
std::accumulate result 5000003.5 took 75.9 ms
std::reduce seq result 5000003.5 took 118.4 ms
std::reduce par result 5000003.5 took 24.6 ms
Average time to operate over 10M items:
accumulate: 79.9ms
reduce par: 28.6ms
reduce seq: 117.8ms

``````