c++parallel-processingc++17reduceaccumulate

Can we use std::reduce to subtract?


I discovered the std::reduce algorithm recently and wanted to compare it with std::accumulate. I found this blog post explaining how std::reduce can be parallelised using std::execution::par. However, the blog post notes that parallelisation only works with operations that are "both associative and commutative."

I wanted to test this out. While I originally thought that subtraction failed due to the algorithm being parallelised, I discovered that it seems std::reduce doesn't give the correct answer for subtraction even when used with std::execution::seq or just run without an execution policy (which should run the algorithm sequentially).

Running this:

std::vector<int> vec = {5, 4, 3, 2, 1};
auto diff = std::reduce(begin(vec), end(vec), 0, std::minus<>{});
std::cout << diff << "\n";

Gives this output:

-1

Am I doing something wrong? Or does std::reduce just never work with subtraction?


Solution

  • Yes you can, with a very slight modification to the calculation. You need to leave the first value out of reduce, and subtract the sum of the other elements.

    #include <iostream>
    #include <execution>
    #include <numeric>
    #include <vector>
    
    int main()
    {
        std::vector<int> vec = { 5, 4, 3, 2, 1 };
        auto sum_of_rest = std::reduce(std::execution::par, vec.begin() + 1, vec.end());
        auto diff = vec.front() - sum_of_rest;
        std::cout << diff << "\n";
        return 0;
    }