Jump to content
  • Advertisement
Sign in to follow this  
GanonPhantom

ThreadPool - Thread per task? or predefined number of threads?

This topic is 3653 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Im currently building myself a threadpool (and before anyone says "There is a boost or .NET thread pool", i know...) But ive ran into a performance/scalability problem. It involves the number of threads the pool holds to complete tasks. I have come up with 2 options, but each one is strong where the other is weak. Such as, if i use the option of thread-per-task, it provides alot of scalability, but gives a small bit of overhead that has to be processed per-task... where as the predefined number of threads provide a small performance boost, and are a bit easier to manage, but are not to scalable when something such as a server comes under a large load of clients. I also thought about a SmartPool, in which it adds threads to the pool as it becomes overloaded. But, the flaw in that is, how do i tell when the thread is no longer needed? Thanks in advance, GanonPhantom

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by GanonPhantom

Such as, if i use the option of thread-per-task, it provides alot of scalability, but gives a small bit of overhead that has to be processed per-task... where as the predefined number of threads provide a small performance boost, and are a bit easier to manage, but are not to scalable when something such as a server comes under a large load of clients.


The usual approach is to have a fixed thread pool, then queue up the tasks.

Quote:
I also thought about a SmartPool, in which it adds threads to the pool as it becomes overloaded. But, the flaw in that is, how do i tell when the thread is no longer needed?


Thread worker is something like this:
while (pool.alive()) {
Task * task = pool.getNextTask();
if (task) {
task->execute();
} else {
pool.waitForTasks();
}
}


WaitForTasks waits on a semaphore, event, you can use something like notify_one() or equivalent to only wake one waiting worker.

Creating threads in an incredibly expensive operation, the biggest gains are to be made by not creating them.

Overhead or not, unless your tasks need to wait for something, such as IO, there isn't much performance to be gained from having more threads than there are CPUs. The advantage is only in somewhat simpler, or at very least sequential code, since OS breaks down your code into small chunks automatically.

For coarse-grained tasks, the overhead usually won't matter compared to benefit you get from using multiple cores without thread switching overhead.

Task-based paralelism is by far the most suitable for some servers. There's even boost::asio that's built on top of it and does all that you mention.

Share this post


Link to post
Share on other sites
A problem ive come across with, when storing tasks, is being able to store more then 1 class type. Such as my task class is like


template<class TClass, typename TArg1> class Task {
public:
void Execute(TClass* Instance, void (TClass::*)(TArg1), TArg1 Argument);
protected:

private:

};




and its hard to keep a queue of these... as there can be multiple classes in use.

Any ideas?

Also, i need some form a generic priority.. ie, this task can not be completed, untill X is done, but be able to do it through the threadpool, and not by always checking to see if the task is done by a ptr.

Thanks,
GanonPhantom

Share this post


Link to post
Share on other sites
Quote:
Original post by GanonPhantom
A problem ive come across with, when storing tasks, is being able to store more then 1 class type. Such as my task class is like

*** Source Snippet Removed ***

and its hard to keep a queue of these... as there can be multiple classes in use.


struct Task {
virtual ~Task();
virtual void execute() = 0;
};


Quote:
Also, i need some form a generic priority.. ie, this task can not be completed, untill X is done, but be able to do it through the threadpool, and not by always checking to see if the task is done by a ptr.


Don't overcomplicate things. For priorities, you can always use priority queue. There's so many problems once you go multi-threaded, that such complex issues soon get out of hand if approached generically.

And make sure to look at boost asio, since it allows for exactly this type of problem (strands - specify which tasks should execute in same thread), as well as use with generic callbacks (anything that has operator()(), boost::function as well).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!