How to write Thread Pools in C++

Ғылым және технология

In this tutorial I explain how thread pools work in C++ and how to implement them.
Tools that I use:
www.virtualbox.org/
kubuntu.org/
code.visualstudio.com/
llvm.org/
clang.org/
mesonbuild.com/index.html
In code:
github.com/renatoGarcia/icecr...
github.com/ZenSepiol
github.com/ocornut/imgui
github.com/epezent/implot

Пікірлер: 25

  • @ohwow2074
    @ohwow2074 Жыл бұрын

    First time seeing what a thread pool is. Thanks for the content. This is indeed interesting. It also shows why many people just prefer std::async over manually managing std::threads/std::jthreads. It's really hard to get it right.

  • @otanoshimi4
    @otanoshimi4 Жыл бұрын

    I am programming in the Windows native thread pool. If you need performance, I think this is true. You can use waiting objects, timers, and Iocp. Therefore, you can use CPU efficiently.

  • @llothar68

    @llothar68

    6 ай бұрын

    Yes, Thread pools can only be implemented efficiently on System Level. It's crazy that Linux does not offerer this but MacOS/Windows for over 20 years now. Also i miss it a lot in Android.

  • @theintjengineer
    @theintjengineer Жыл бұрын

    Nice video and also the visualisation. Also, if you were to use the new concurrency features of C++20, you would greatly simplify your code. I could think of, besides the condition variables, and the locks, using jthread instead and and its cooperative interruption feature (with stop_source and stop_token), binary_semaphore for shutdown or is_empty?, are_we_done?, etc. stuff, and latches|barriers (probably barrier with arrive_and_wait(), if you wanna make that a multi-shot thing). But still, you did the hard job haha. Be safe, Mate.

  • @ZenSepiol

    @ZenSepiol

    Жыл бұрын

    Yes, I was lazy and didn't want to update the code to C++20. C++23 even has the move only function which would greatly improve the code as well. I will update make a vid about the update.

  • @HylianEvil

    @HylianEvil

    11 ай бұрын

    @@ZenSepiol Very curious watch a vid using the new features

  • @noel350

    @noel350

    7 күн бұрын

    @@ZenSepiol So long as the complex stuff is hid behind a neat interface - who cares? You only need to look at it when it breaks.

  • @dagoberttrump9290
    @dagoberttrump9290 Жыл бұрын

    Good video. A few notes: - why did you use std::bind inside addtask? You can simply stuff the function inside a packaged task (note that the ctor is marked explicit so youhave to do an explicit conversion) - don't wrap a packaged task in a shared pointer, as a packaged tas already is a shared ptr (at leastin libstdc++) - in general your implementation is a good entry level example but it's not very cache friendly and scalability could be better. Soif you want todo some serious lifting you should look into work stealing task pools. On the other hand, this is completely sufficient for a simple game engine or an app.

  • @ZenSepiol

    @ZenSepiol

    Жыл бұрын

    - About the bind, I don't know, it just happen and I didn't really think about it. - The shared pointer is not necessary for the shared state, but for the type erasure with the lambda function. Since a normal function inside the package task is not a move only type, the capture of the lambda needs to be a copy. To be able to do the copy, I use the shared ptr. In C++23 you can use the move only function, stuff that into the package task and then move it inside the capture of the lambda. That way you don't need the shared ptr. - You are correct. It depends on what you plan to use the thread pool for. The main driver is, how often do you expect your queue to be empty? If often, the current implementation with a shared queue across all threads is the most efficient. If your thread pool is completly busy all the time, I would switch to an implementation with a single queue per thread and implement task stealing. In fact, we use several thread pool implementations based on the task and data at hand.

  • @dagoberttrump9290

    @dagoberttrump9290

    Жыл бұрын

    @@ZenSepiol You don't need type erasue in this case, a packaged task will always accept anything that corresponds to its return value and arguments - which of course in your case you have. But think about it: If you were to just accept only functions that have void return type and zero arguments you could get away with it while at the same time be more transparent. You don't need to do the extra step to stuff the arguments into the functor's fields (using closures), but have the user do it beforehand. This way it is more transparent to the user how the arguments will be used and he will think twice about passing in references that might run out of scope when the caller exits. You also avoid double indirection of operator()() on every loop iteration.

  • @sritharan20
    @sritharan20 Жыл бұрын

    Also when you get some time can you make a video on thread concurrency, thread exception handler, process mutexing pls

  • @ZenSepiol

    @ZenSepiol

    Жыл бұрын

    I'll see what I can do! All very good topics to cover.

  • @laurin__
    @laurin__6 ай бұрын

    thanks youu uwuw, i'll need to research templates futures and mutex stuff first & come back.. ;)) #godblessamerica #wtfisakilometar

  • @sritharan20
    @sritharan20 Жыл бұрын

    Thank you Zen. Appreciate it. Very elegant code. Can you share the link to the code in your Github pls, i dont see them.

  • @ZenSepiol

    @ZenSepiol

    Жыл бұрын

    Here you go: github.com/ZenSepiol/Dockerized-Dear-ImGui/blob/main/src/lib/app_base/thread_pool.hpp

  • @sritharan20

    @sritharan20

    Жыл бұрын

    @@ZenSepiol Thank you

  • @VHTTHongLinh
    @VHTTHongLinh8 ай бұрын

    Can you share information relate to what the matrix panel show 1240 number behind you =))) ?

  • @ZenSepiol

    @ZenSepiol

    8 ай бұрын

    That was my Subscriber count while making the video 😃

  • @janwilmans5954
    @janwilmans59544 ай бұрын

    spurious wake ups are not bugs, for example you can get a spurious wakeup when a laptop comes out of sleep mode, there is literally no other way to handle that without re-checking the condition

  • @janwilmans5954
    @janwilmans59544 ай бұрын

    no need to use bind: template auto AddTask(Fn fn) { auto pTask = std::make_shared(fn); auto f = pTask->get_future(); Add([pTask]() { (*pTask)(); }); return f; }

  • @eladon19153

    @eladon19153

    12 күн бұрын

    But then wouldn't you be fixated to no argument (I mean, return_type(void)) functions? I might be wrong, but how can we make it so we could actually send functions with arguments?

Келесі