Search code examples
multithreadingthreadpoolboost-thread

can a threadpool(like boost) be initialized into a class constructor and used when class members are called?


Lets say I have a threadpool (example might be http://threadpool.sourceforge.net/); And i have this code:

class Demigod{ 
public:
   Demigod();
   void AskObedienceFast();
   void AskObedienceSlow();
   void WorkHardGodDamn();
   ~Demigod();
private:
   ThreadPool m_PitySlaves;
   int m_Quota;
};
Demigod::Demigod() : m_PitySlaves(manyPlease) { 
}
void Demigod::WorkHardGodDamn(){ 
    //something irelevant just to annoy slaves
}
void Demigod::AskObedienceFast() { 
    for(int q=0; q<m_Quota; ++q){
       m_PitySlaves.schedule(boost::bind(&Demigod::WorkHardGodDamn, this)); 
    }
    m_PitySlaves.wait();
}
void Demigod::AskObedienceSlow() { 
    ThreadPool poorSouls;
    for(int q=0; q<m_Quota; ++q){
       poorSouls.schedule(boost::bind(&Demigod::WorkHardGodDamn, this)); 
    }
    poorSouls.wait();
}
void main(){ 
   Demigod someDude;
   for(size_t i=0; i<dontstop; ++i){ 
      someDude.AskObedienceFast();
   }
}

Can AskObedienceFast be faster and work in comparison with AskObedienceSlow? This way I can have some thread (slaves) and be ready for work anytime I ask without having to lose time making the threadpool at every call. I know I can verify the code myself, but my question is more broad, if this is not fundamentally lose performance somewhere else, like those threads in the threadpool doing some waiting process? It comes down to avoiding expensive threadpool initialization (and threads).


Solution

  • There is nothing like "waiting process". If a thread is waiting (on a condition), scheduler is simply skipping it, therefore such thread does not do anything and is not being switched in and out. As you very correctly pointed out, the most expensive task in threading is setting up the thread (though all major OSes are taking steps in minimizing it as much as possible, to keep pace with the recent multiplication of cores), closely followed by switching thread contexts. So you can see why AskObedienceSlow is horrible. Your temporaries should be only "cheap" structures, which take as little time as possible for construction and destruction. ThreadPool definitely isn't one such. Even AskObedienceFast won't protect you from the context switching overhead, but that's why bigger thread pools aren't always better and the best performing size is a matter of careful balancing dependent on your actual workload. Some of the best performing high load, high throughput applications are single-thread, message-passing designs for this very reason. Programming languages used for such applications (like Erlang) are explicitly threadless.