Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do separate arrive and wait exist in C++20 barrier?

Tags:

c++

c++20

barrier

C++20 std::barrier has arrive_and_wait method, which is what pretty much every synchronization barrier implementation has.

But it also has separate arrive and wait. Why do these functions exist?

like image 679
Alex Guteniev Avatar asked Jul 27 '20 16:07

Alex Guteniev


People also ask

What is the difference between wait and generation in c++20?

You might like to know that there's a std::barrier in C++20. Your wait is what C++20 calls arrive_and_wait. Your generation is what C++20 calls the "phase."

Is it possible to implement a barreir in C++?

I've implemented a barreir in C++ close to one showed here. In the project code it's used only with two threads and seems to work. A synthetic test didn't expose any flaws too. But I suspect that on some machines it segfaults and/or falls through wait () call.

What's next for shared_ptr<T> atomic operations with C++20?

Consequently, the atomic operations for std::shared_ptr<T> are deprecated with C++20. What's next? With C++20, threads can be cooperatively interrupted. Let me show you in my next, what that means.

What is wait system call in C?

Wait System Call in C. A call to wait() blocks the calling process until one of its child processes exits or a signal is received. After child process terminates, parent continues its execution after wait system call instruction. Child process may terminate due to any of these: It calls exit();


Video Answer


1 Answers

OK, so you've got a bunch of threads that have to do some kind of synchronized tasks. These tasks are grouped into phases: the tasks from one phase will use data produced by tasks from a previous phase, and all previous phase work must be done before any next-phase work can start. Let us call any work that requires data from a previous phase "in-phase" work.

However, let's say that not everything you need to do actually requires data from a previous phase. There could be some individual work items that a thread could perform that doesn't read data from a previous phase. Let's call this "out-of-phase" work.

Note that this is "out-of-phase" relative to a particular barrier. It could be that the work is in-phase of a different barrier.

If you try to do this out-of-phase work before calling arrive_and_wait, then you could be blocking all of the other threads from doing something even though you are done with the actual work they're waiting on. Depending on the balance between in-phase and out-of-phase work, that could be a lot of wasted performance.

So if a thread has finished its in-phase work and has some out-of-phase work to do, it can arrive. This potentially frees up all of the other threads if they too are finished with their in-phase work. The thread can then go process some out-of-phase work potentially asynchronously with work being done from the next phase. Once the out-of-phase work is done, the thread can wait on the token generated by its call to arrive, which if the next phase has started, will return without blocking.

Indeed, if the amount of in-phase work is much less than the amount of out-of-phase work, then this pattern means that threads almost never block. The barrier just acts as a multi-thread atomic ordering operation, never a blocking one.

like image 140
Nicol Bolas Avatar answered Nov 10 '22 23:11

Nicol Bolas