The C + + Standard Template Library provides an auxiliary function-std::thread::hardware_concurrency (), through which we can get the number of threads that an application can actually execute concurrently. The following example implements a concurrent version of the std::accumulate that splits the work into multiple threads, and in order to avoid the overhead of too many threads, the program specifies the minimum number of data per thread to process.
Header files and summation operations:
#include <thread>
#include <numeric>
#include <algorithm>
#include <functional >
#include <vector>
#include <iostream>
template<typename iterator,typename t>
struct Accumulate_block
{
void operator () (iterator first,iterator last,t& result)
{
result=std::accumulate (first,last, result);
}
;
The concurrent summation method is as follows: On my computer, the hardware can have a concurrent thread number of 8.
Template<typename iterator,typename t> T parallel_accumulate (iterator first,iterator Last,T init) {unsigned lon
G Const LENGTH=STD::d istance (First,last);
If the input data is empty, it returns the initial value if (!length) return init;
Calculates the maximum number of threads required, each thread calculates at least 25 data unsigned long const min_per_thread=25;
unsigned long const max_threads= (length+min_per_thread-1)/min_per_thread;
Gets the number of concurrent threads for hardware unsigned long const hardware_threads= std::thread::hardware_concurrency ();
Calculates the number of threads that are actually being created unsigned long const num_threads= std::min (hardware_threads!=0?hardware_threads:2,max_threads);
Based on the number of threads, split data unsigned long const block_size=length/num_threads;
Create a container and thread std::vector<t> results (num_threads) for each thread to compute the results;
Std::vector<std::thread> threads (num_threads-1);
Iterator Block_start=first;
For (unsigned long i=0;i< (num_threads-1); ++i) {iterator block_end=block_start;
Moving iterators Std::advance (block_end,block_size);
Starts a new thread, processes a piece of data Threads[i]=std::thread (accumulate_block<iterator,t> (),
Block_start,block_end,std::ref (Results[i]));
Prepare data block_start=block_end for the next thread; //When all child threads are started to compute the data, this thread computes the last piece of Data accumulate_block<iterator,t> () (Block_start,last,results[num_thr
EADS-1]); Use Fore_each to perform a join operation on all threads, waiting for them to execute the end Std::for_each (Threads.begin (), Threads.end (), STD::MEM_FN (&
Std::thread::join));
Finally, all the calculated results are summed return Std::accumulate (Results.begin (), Results.end (), init); }Main method:
int main ()
{
std::cout << "Threads:" << std::thread::hardware_concurrency () << Std::endl;
Std::vector<int> VI;
for (int i=0;i<100;++i)
{
vi.push_back (a);
}
int Sum=parallel_accumulate (Vi.begin (), Vi.end (), 5);
std::cout<< "sum=" <<sum<<std::endl;
}
The results of the procedure are as follows:
Threads:8
sum=1005
The type of the identifier for the thread is std::thread::id, and there are two ways to get a thread identifier, one by calling the get_id () method of the Std::thread object that is associated to the thread, and another by calling Std::this_thread within a thread:: GET_ID (). Thread identifiers are typically used to differentiate between the main thread and the child thread, and in some cases certain actions can be made in the main thread
Std::thread::id Master_thread;
void Some_core_part_of_algorithm ()
{
if (std::this_thread::get_id () ==master_thread)
{
Do_ Master_thread_work ();
}
Do_common_work ();
}