Today, using C + + implements the parallel calculation version of the accumulate function in the standard library header file <numeric>, the code is as follows, the comments are written in more detail, only a few of them are described:
① the implementation assumes that no exceptions occur, so there is no processing of possible exceptions
② the statement on line 42nd:
const unsigned int num_thread = Std::min ((Hardware_thread! = 0? hardware_thread:2), Max_thread);
The number of threads to run is a small value for the maximum number of threads and the number of hardware threads that are calculated. This is because if the number of threads running exceeds the range of hardware support, the CPU context switch degrades performance. again, because the value of Hardware_thread may be 0, in this case the user needs to replace the number of threads themselves, in code 2, because running too many threads on a single core can cause performance degradation, but too few threads will miss the available concurrency.
③ The 44th Line calculates the number of elements per thread operation, the calculation may not be divisible, but there is no need to worry because the last thread will handle all the remaining elements, as shown in the 68th line of statements:
accum<iterator, t> (Block_begin, Last, results[num_thread-1]);
④ Note the statement on line 64th:
Threads[i] = Thread (Accum<iterator, t> (), Block_begin, Block_end, Std::ref (Results[i]));
The third parameter to the function passed to the thread is incremented by Std::ref (), which is included in the header file <functional>. In general, the constructor of the thread object simply copies the user-supplied arguments and passes them to the callable object associated with the thread. That is, the callable object receives a copy of the parameter, and its modifications do not affect the parameters passed by the original user. If you need to receive a reference version of a parameter, you need to use the Std::ref () function.
1 //implementing parallel versions of the accumulate function in the standard library header file <numeric>2#include <iostream>3#include <thread>4#include <numeric>5#include <algorithm>6#include <vector>7#include <functional>8#include <utility>9 Ten usingStd::thread; One usingstd::vector; A usingstd::accumulate; - usingstd::cout; - usingStd::endl; the -Template <typename Iterator, TypeName t>classAccum - { - Public: + void operator() (Iterator first, Iterator last, T &sum) - { +sum =Std::accumulate (First, last, sum); A } at }; - -Template <typename Iterator, TypeName t> -T Parallelaccum (Iterator First, Iterator last, T &sum) - { - //calculate the number of elements contained in an iterator in ConstUnsignedintLen =std::d istance (first, last); - //if no elements in the iterator are returned directly to if(!len) + { - returnsum; the } * //minimum number of elements processed by each thread $ ConstUnsignedintMin_per_thread = -;Panax Notoginseng //gets the maximum number of threads, rounding up - ConstUnsignedintMax_thread = (Len-1+ min_per_thread)/Min_per_thread; the //gets the number of concurrent threads supported by the machine + ConstUnsignedintHardware_thread =thread::hardware_concurrency (); A //take the smaller of the two, while avoiding too few threads the ConstUnsignedintNum_thread = Std::min ((Hardware_thread! =0? Hardware_thread:2), max_thread); + //Finally, the number of elements that are actually processed per thread - ConstUnsignedintBlock_size = len/Num_thread; $ //Save the cumulative results for each thread $Vector<t>results (num_thread); - //boot than num_thread-1 threads because the main function itself has a thread open -Vector<thread> Threads (Num_thread-1); the // -cout <<"Number of elements:"<< Len <<Endl;Wuyicout <<"Hardware Concurrency:"<< Hardware_thread <<Endl; thecout <<"Maximum Number of threads:"<< Max_thread <<Endl; -cout <<"Number of Threads:"<< Num_thread <<Endl; Wucout <<"Block Size:"<< block_size <<Endl; -cout <<"Started parallel Calculating ..."<<Endl; About //Start Parallel Computing $Iterator Block_begin =First ; - for(unsignedinti =0; I < (Num_thread-1); ++i) - { -Iterator Block_end =Block_begin; A //pushes the iterator forward one block, reaching the end of the current block + std::advance (Block_end, block_size); the //passing parameters, typically the constructor of thread will copy the supplied arguments and need to convert the template argument to a reference -Threads[i] = Thread (Accum<iterator, t> (), Block_begin, Block_end, std::ref(Results[i])); $Block_begin =Block_end; the } the //processing the last thread, because the result of Block_size = Len/num_thread is not necessarily an integer, the thread processes all remaining elements theAccum<iterator, T> () (Block_begin, Last, Results[num_thread-1]); the //call Join () for all threads in Threads -Std::for_each (Threads.begin (), Threads.end (), STD::MEM_FN (&thread::join)); in // the returnaccumulate (Results.begin (), Results.end (), sum); the } About the intMain () the { thevector<int>I_vec; + intsum =0; - for(inti =1; I! =501; ++i) the {Bayi I_vec.push_back (i); the } thesum =Parallelaccum (I_vec.cbegin (), I_vec.cend (), sum); -cout <<"sum ="<< sum <<Endl; -System"Pause"); the return 0; the}
C + + Multithreaded programming: Implementing a parallel computing version of the standard library accumulate function