Computing sum of elements with mutlithreads
Better algorithm

So the main practical improvement would be to use a roll. Atomics are very slow if multiple threads take turns in accessing it in clockwise/anticlockwise manner, e.g. like a carousel. Let's define the algorithm:


Retrieve number of physical threads, e.g. cores. Sometimes it is not available, so setting it to 4 would be a pretty good guess these days. Number of threads visible to OS would be important if algorithm would have diverse workload, but this is not the case here.
While not reached the end of the vector:

2.1 Allocate all physical threads to sum 1000 numbers in the range. The number might need to be fine tuned, but I believe this already should outweigh the cost of the thread creation.

2.2. Sum the results of each number into result.


The process is actually much harder than it looks like. One has to create a vector of std::promises and get std::futures of them, then create small function that would set the future from outside, then join threads ... Well I guess you got the point. This question should help out with that.

Compute in place

Since the algorithm does read-only access on the container, it could be just passed by reference. The master function could schedule the work and then collect the result.

Iterators

I believe that if the properties of std::vector are not exploited, it doesn't make much sense to hardcode it. Iterators provide powerful abstraction, though they take time to get used to them. Also, they could be used to delegate to std::accumulate, e.g. in the small function it would just call accumulate on range.

More power

I believe the function could be extended without much effort and still retain compatibility and easy of use of original one. Something like this:

template &lt;typename RandomAcessIt,
          typename T = std::iterator_traits&lt;RandomAcessIt&gt;::value_type,
          typename BinaryOp = std::plus&lt;&gt;&gt;
T accumulate(parallel_compute_tag, RandomAcessIt first, RandomAcessIt last, T initvalue = {}, BinaryOp op = {})


So default would still be +, but it could be changed to whatever heart likes. And then instead of using + one could just op(lhs, rhs).

Rolling

Here is a terrible picture (I made my best at it)



As you can see, the scheduled threads "roll into" master thread to provide the result. That is why I said rolling approach. I don't really know the term for this though.