问题
I've just started diving into multithreading using the standard library today. Below is what I've come up with so far. Though it works in principle, it does not start a new thread once one has finished, but rather starts 4 threads once the last 4 finished, so if the tasks take an unequal amount of time, it isn't very efficient. Also, if they don't finish in the correct order, they have to wait for the succeeding work to finish until their results are evaluated.
How could I achieve always having 4 threads (until the work runs out)? I would think you would need to employ some sort of watcher function, but I don't see how it is possible exactly without signals/slots. I'd also be happy if you could point me to the correct manuals online.
Also, since I have no experience using multiprocessing before today, please tell me where I might have employed bad practice.
Thank you in advance!
mueslo
Here is the threaded task:
void burn_task(MyClass* obj)
{
//computationally intensive
obj->burn();
}
And here is how it is called:
void getsStuffDone()
{
//initialise everything
int samples = 1000;
int num_threads = 4;
std::vector<MyClass*> myclasslist;
std::vector<std::thread*> threadlist;
myclasslist.resize(num_threads);
threadlist.resize(num_threads);
int i = 0;
//do the work
while(i+1<samples)
{
//current_num_threads = min(num_threads, num_tasks_left)
int current_num_threads = (samples-i-1>num_threads)? num_threads : samples-i-1;
//create threads
for(int t=0; t<current_num_threads; ++t)
{
myclasslist[t] = new MyClass(other_parameters,i+1); //i+1 so seed is never zero
threadlist[t] = new std::thread(burn_task, myclasslist[t]);
++i;
}
//wait to finish, evaluate and clean up (delete)
for(int t=0; t<current_num_threads; ++t)
{
threadlist[t]->join();
useResultsContainedWithin(myclasslist[t])
delete myclasslist[t];
delete threadlist[t];
}
threadlist.clear();
}
}
回答1:
A common approach for handling a set number of threads performing some task is to start X threads, and then let each thread pick it's "work" from a common queue. In a really simple case, you'd simply, instead of doing i+1
and i++
in the loop that creates the thread, let i
be a std::atomic<int>
, and do:
void some_thread_function()
{
for(;;)
{
int work_on = i.fetch_add(1); // "work_on = i++;"
if (work_on >= samples)
break;
... // do actual work
}
}
In a more complex case, you'd have a waitable queue that contains a more complex datatype to describe the "work" to be done.
This means you always have the "right" number of threads, and there is no overhead of creating/tearing down threads (if the threads run for quite some time (tenths of a second or longer), this is not an issue anyway, but for "short" runtimes it is quite possibly a factor.
来源:https://stackoverflow.com/questions/19144570/how-can-i-make-sure-there-are-a-given-number-of-threads-at-all-times-also-is