0

I am facing a problem because of high overhead of pthread_create. I have looked the internet for a good threadpool library, but I didn't find one that suits my project, or they simply did not work.

I am quite new to c++, and my programming skills are pretty basic, but good. I programmed a lot (over 5 years), I just did not do any object oriented projects or even used data structures.

I would really appreciate any material or guides that can help me get the experience and knowledge needed to create my own thread pool.

Due to constraints in my current project, I will work on normal c++ (not C++11) on a windows 10 (mingw32) and I have to avoid using any boost libraries.

as requested: About the problem:

I am writing a computational expensive project. I want to make it run faster, so I decided to use pthreads. The problem, however, is that the thread creation is inside a loop, and pthread_create is called 64 times.

After a lot of research and trying I figured out that threadpools are the solution here, but I spent over 3 days getting the implementations I found online to work, but to no avail, so I decided to write my own thread pool implementation.

About an example of the code you can check: How can I reduce the effect of pthread_join. Mingw32, c++

But there I realized its the thread create, not thread_join that causes the performance to worsen.

Community
  • 1
  • 1
user304584
  • 487
  • 1
  • 3
  • 14
  • Can you please be more specific with the problem you are having? Like is it the pool itself? Work-queue? The threads? Putting it all together? – Some programmer dude Sep 16 '15 at 14:04
  • 2
    if you're OK with Boost, there's a really efficient (and crossplatform) way for task-based multithreading using Boost.Asio: http://stackoverflow.com/questions/19500404/how-to-create-a-thread-pool-using-boost-in-c – Andriy Tylychko Sep 16 '15 at 14:12
  • I hope this edit clarifies the problem better. I will try the boost solution, but i am limited with the size of my project so I can't include large libraries. – user304584 Sep 16 '15 at 14:15
  • 2
    for computational expensive project I'd recommend not to invent the wheel and not to try to mess with low-level multithreading but use task-based multithreading that is actually using thread pool in its implementation. One of the best implementation is Intel Threading Building Blocks: https://www.threadingbuildingblocks.org/ – Andriy Tylychko Sep 16 '15 at 14:15
  • I looked at threadingbuildingblocks.org , its 42 MB, this is huge. – user304584 Sep 16 '15 at 14:26
  • These days with memory in the gigabytes range and disks up to several terabytes, I think you need to rethink your scales, tens of megabytes *on disk* (likely much less in memory) is not very large. Using the latest standard and its functionality, as well as utility libraries like Boost or Intel TBB can really boost your productivity as a programmer. – Some programmer dude Sep 17 '15 at 04:59

1 Answers1

3

Despites some comments over there, basic thread pools are not that complicated. They are simpler than good logger, for instance :)

First, a couple of statements.

  • pthread_create is VERY lightweight. It is unlikely it is a real bottleneck. If your compulation time is comparable with the time it takes to create a thread, you might not need a thread to begin with.
  • C++11 is the NORMAL C++. C++03 is referred to as ARCHAIC. I strongly urge you to rethink 'constraints' of your project (since you do not seem to be using external libraries, ABI incompatibility should not a problem for you), and forgo an 11 years old, outdated and inadequate compiler.

Now, to thread pools. The basic thread pool contains of 3 major parts: incoming message queue, outgoing message queue and a bunch of threads servicing those queues. Depending on the design, those messages might be either a real message (i.e. string saying "dear thread, please compute 5 + 10"), or it can be a callable thing, which thread just calls. A type-erased function object works best here. So, when the message is a text, thread function will have a bunch of if() statements to handle different messages, when it is a callable, it will simply call this callable. Text messages are easier to maintain, since you have everything you need to care about in the text itself. Callable objects, on the other hand, have a lifetime, which you should be thinkig of - for instance, putting local variables as callables will be a guaranteed disaster.

The other piece is the message queue itself. First of all, there are two viable design choices - every thread has it's own queue, or there is a shared queue to be used by all threads. The benefits of the first is that there is no contention on the queue - there is one reader and one writer. Shared queue has contention, but the benefit is that it provides for natural load balancing - threads will simply pick up messages as they are ready to process a new one.

Lockless queue is usually a good choice to be used as a message queue.

SergeyA
  • 61,605
  • 5
  • 78
  • 137