Practical example to barriers (pthread_barrier)
HTML-код
- Опубликовано: 2 июн 2024
- Source code can be found here:
code-vault.net/lesson/18ec194...
===== Support us through our store =====
code-vault.net/shop
===== Check out our website =====
code-vault.net
===== Check out our Discord server =====
discord.code-vault.net
You are an amazing teacher. Love the way you simplify all such complex topics. Please make more videos... Like these on ompi and cuda as soon possible. Thanks a lot. May God bless you. 🤗
I'll look into those too! Thanks!
Thankyou, I really need help with this as soon as posible
thank you for the help. You are an amazing teacher !
Amazing video and very well taught! Thank you!
God bless you! ☺Thanks for the videos 👍
You are just next to amazing👏👏👏
That was great thank you!
Great video, thanks.
excellent tutorials
Very useful!
Wish you were on youtube back when I was in college.
Thank you
Hi codevault, A question regarding the last parameter of barrier initialization.
Would waiting on these barrier basically do nothing?
pthread_barrier_init(&our_barrier1,NULL,0);
pthread_barrier_init(&our_barrier2,NULL,1);
Is there any reason to use 0 or 1?
I don't know of a reason to use any of those. Barrier with count 0 is undefined behaviour, so not supported by the standard. Barrier with count 1... will work as expected... but would be useless
@@CodeVault agreed. appreciate it
So if I am understanding this correctly, when you wanna know if a single thread has completed its execution of a particular code segment, you use condition variables to signal or broadcast, but when you wanna know if multiple threads has completed their execution of a common code segment, you use barriers?
Yes, you could put it that way. Usually a condition variables's signal or broadcast signals to other threads that the condition they are checking *might* have changed. Whereas barriers are just as you explained.
there is something that I'm not understanding quite well,
I understood that the barrier makes the threads to wait until the barrier count of threads is satisfied,
but when u initialized the barrier with Thread_num+1 in main function and then used it in the roll_dice function
there are just 8 threads are going to enter the roll_dice function and wait at the barrier , but the barrier count is 9
so we have one last thread to satisfy the barrier count
u said that main is the last thread but how the main is gonna enter the roll_dice function and go through the barrier ?
I didn't understand this part quite well , if u could explain it , I appreciate it.
and thanks alot for your content, it's just amazing ❤
There are 9 threads in this example. 8 are the ones created by us using pthread_create and the 9th one is the main thread we get when executing the program. To affect the barrier we don't have to call roll_dice, we just need to call one of the pthread_barrier functions in the main function. That's what we do in the example
In the previous video of introduction to barriers when you initialised the barrier with 3, and created 2 threads, it did not work and kept waiting at the barrier. but by this logic it should have worked because there will be total three threads( two created by us using pthread_create and one main).
Can you pls explain this @@CodeVault
@@vivekdhanda5540 The program is calling pthread_barrier_wait with only the 2 threads that we created. You will notice that the main thread doesn't call that function. That's why it's not crossing the barrier
ohh ok, thanks for the reply @@CodeVault
10:00 Also we could do calculation after "pthread_join" for loop. But I understand the problem. The real case could not be that simple.
Dear CodeVault, Im trying to compile using the pthread library and its having trouble to recognize pthread_barrier_t. And in man pthread barriers don't show up. So where do they come from? Thanks in advanced (;
Hmm, never encountered this before. A quick google search and here should be your solution: stackoverflow.com/questions/61647896/unknown-type-name-pthread-barrier-t
Man you are better than my college profesor.
Why can not we use the barrierRolledDice again? Why do we have to create another one?
Also would broadcast do the work?
You can. But it makes for more legible code. People always forget to give meaningful names to mutexes, condition variables and other synchronization objects which becomes a big issue on larger projects.
Broadcast with condition variables? It might be more complicated because, when broadcasting, you're not guaranteed that ALL threads got to the wait. With barriers, that is guaranteed.
Wouldn't only using the 2nd barrier (barrierCalculated) work for us? Cause shouldn't we just have a barrier in the main thread when we have calculated what is the win condition and can then let threads check if they won. I ran the code and it works but if there is something else that might be happening do tell.
No, that's not right, because, if you only have 1 barrier, the other threads could pass through that barrier AND check their status BEFORE the main thread is able to calculate the results
@@CodeVault aah true makes sense. Thanks for the reply.
Can we implement this example with the signals?
Signals aren't really meant to be used this way. They are a really low level inter-process messaging system used to send "critical" and immediately actionable tasks. You could implement this using pipes though.
@@CodeVault hmmm thank you
At 11:10, why can't we use semaphores for this purpose?
Because with barriers there's no thread that says "ok, you can go forward". It's all automatic based on how many threads are waiting at that spot. You can probably do the same thing with semaphores, but it's gonna take more than just replacing the barriers with semaphores
Thank you for example. Can you please show some examples for linux io_uring. Io_uring makes sync call async.
I will look into it
@@CodeVault thank you
Can''t we use also condition variable broadcast instead of barrierCalculated?
No, because, it's not guaranteed that, when you broadcast, ALL the threads were waiting at the condition variable's wait
@@CodeVault Oh, it seemed to me that after barrier named "barrierRolledDice" they are all on the same page and just have to wait until main thread will calculate result, and instead of "barrierCalculated" there could be a broadcast condition variable. But the trick probably is that it is possible that main thread will calculate the result, broadcast condition, while not all remaining threads started waiting for that signal, as thread execution sequence is random. Is this a right understanding?
Exactly. With barriers, ALL threads have to wait until they continue. Of course, I think you can do it without barriers too... although you can't just replace the barriers with condition variables. I'll let you think about it!
Thanks for your incredible videos. Would you help me answer the above questions:
In ex1.c (6.1), which of the following properties achieved:
(1) Mutual exclusion but not progress
(2) Progress but not mutual exclusion
(3) Neither mutual exclusion nor progress
(4) Both mutual exclusion and progress
Please explain?
1.2
To which arguments (in 6.1) is correct and which does not:
(1) always exits. when threads = 2 or threads 2
for the above code:
int S1 = 0;
int S2 = 0;
int x = 0;
int run = 1;
void Producer(void) {
while(run) {
while (S1 == S2);
x++;
__sync_synchronize();
S1 = S2;
__sync_synchronize();
}
}
void Consumer(void) {
while(run) {
while (S1 != S2);
x--;
__sync_synchronize();
S1 = !S2;
__sync_synchronize();
}
}
void* Worker(void *func) {
long func_id = (long)func & 0x1;
printf("%s %d
",__func__, (int)func_id);
switch (func_id) {
case 0:
Producer();
break;
case 1:
Consumer();
break;
}
return NULL;
}
int main(int argc, char *argv[]) {
pthread_t t[argc];
pthread_attr_t at;
cpu_set_t cpuset;
int threads;
int i;
#define MAX_PROCESSORS 4 // Minimal processors is 2.
threads = argc > 1 ? (( atoi(argv[1]) < 4) ? atoi(argv[1]):
MAX_PROCESSORS ) : 1;
for (i = 0;i < threads; i++){
CPU_ZERO(&cpuset);
CPU_SET(i, &cpuset);
pthread_attr_init(&at);
pthread_attr_setaffinity_np(&at, sizeof(cpuset), &cpuset);
if (pthread_create(&t[i], &at , Worker, (void *) (long)i) ) {
perror("pthread create 1 error
"); }
}
do {
sleep(1);
} while(x < 0);
run = 0;
void *val;
for(i = 0; i < threads; i++)
pthread_join(t[i], &val);
printf("x=%d
", x);
}
Sorry, I'm not here to solve your homework. First try answering the questions yourself