Lecture 16

wjddlstjd396·2022년 2월 16일

CS343-Parallel Programming

목록 보기

6.3.3 Barrier Lock

It is syncronization lock.
It cannot be used for mutual exclusion

The barrier has some state within it.

  • some counters
  • some flags!
  • some more information

most barriers have internal locking

EX) S1, S2, S3 must all execute before S5, S6, S7

in this example, n in b(n) is indicating how many tasks are involved.
so once b.block() is called from 3 threads, barrier will unblock them all.

The lost one to call b.block() must wake other blocked threads.

many times you want to get the results of the syncronized works.

you can make this work by having coordinator

Barrier start(N+1), end(N+1); //  +1 is for coordinator

//// coordinator's job
  start.block(); // wait for threads to start
  //do other work
  end.block(); // wait for threads to end
  // sum up the result

//// Workers
  // do actual work
  //close down
//// uBarrier implimentation

uBarrier is very complicated because it is also a full coroutine

#include <uBarrier.h>
_Cormonitor uBarrier{
  void main(){ for (;;) suspend(); }
  virtual void last() {resume();}
  uBarrier(unsigned int total);
  unsigned int total() const;
  unsigned int waiters() const;
  void reset(unsigned int total);
  virtual void block();

unsigned int total is the number of threads involved in the race.
you can change [total] with reset, but only when no threads are on block.

it has internal syncronization lock and no barging.

Need to inherite and refine

  • last
  • block

members of uBarrier.

EX) matrix sum example - A4 pattern

_Cormonitor Accumulator: public uBarrier{
  int total_=0, temp;
  uBaseTask *Nth_ = nullptr;
  void last(){
    temp = total_; total_ = 0;
    Nth_ = &uThisTask();
  Accumulator(int rows): uBarrier(rows){}
  void block(int subtotal){ // this will be working as critical section
    total_ += subtotal;
  int total(){return temp;}
  uBaseTask * Nth() {return Nth_;}

_Task Adder{
  int * row, size;
  Accumulator & acc;
  void main(){
    int subtotal = 0;
    for(unsigned int r=0; r<size; r++) subtotal += row[r];
    acc.block(subtotal); // provide subt total
  Adder(int row[], int size, Accumulator & acc):
    size(size), row(row), acc(acc) {}

int main(){
  enum {rows = 10, cols = 10};
  int matrix[rows][cols];
  Adder * adders[rows];
  Accumulator acc(rows); // set berrier with 'rows' number of threads
  //read matrix
  for(unsigned int r=0; r < rows; r++)
    adders[r] = new Adder(matrix[r],cols,acc);
  for(unsigned int r=0; r < rows; r++)
  	delete adders[r];
  cout << acc.total() << " " << acc.Nth() << endl;

You cannot use barrier with COFOR
that is because COFOR may create threads by blocks and theres no way it to tell how many of tasks are in a block.

6.3.4 Binary Semaphore

Semaphore lock()

lock.P() // to acquire
lock.V() // to release the lock

lock has a counter in it.
initially its 1.
P() will decrement counter
V() will increment counter.

P() on a lock of counter 0 will wait until it is V()ed.

V() on a lock of counter >0 may increment counter above 1 or throw error
this depends on implementation

EX) syncronization with semaphore

EX) mutual exclusion with semaphore

Implementation of binary semaphore

Its nearly identical with the lock implementation, but it gives an option to start the lock in either closed or open state

6.3.5 Counting Semaphore

A lock with multiple states rather than 0 or 1.

Allows N simultaneous tasks to enter critical sections.


0개의 댓글