Module 7: "Parallel Programming"
  Lecture 13: "Parallelizing a Sequential Program"
 

Mutual exclusion

  • Use LOCK/UNLOCK around critical sections
    • Updates to shared variable diff  must be sequential
    • Heavily contended locks may degrade performance
    • Try to minimize the use of critical sections: they are sequential anyway and will limit speedup
    • This is the reason for using a local_diff  instead of accessing gm->diff  every time
    • Also, minimize the size of critical section because the longer you hold the lock, longer will be the waiting time for other processors at lock acquire

LOCK optimization

  • Suppose each processor updates a shared variable holding a global cost value, only if its local cost is less than the global cost: found frequently in minimization problems
    LOCK (gm->cost_lock);               
    if (my_cost < gm->cost) { 
    gm->cost = my_cost;                
    }
    UNLOCK (gm->cost_lock);
    /* May lead to heavy lock contention if everyone tries to update at the same time */

    if (my_cost < gm->cost) {
    LOCK (gm->cost_lock);
    if (my_cost < gm->cost)
    { /* make sure*/
    gm->cost = my_cost;
    }
    UNLOCK (gm->cost_lock);
    } /* this works because gm->cost is monotonically decreasing */

More synchronization

  • Global synchronization
    • Through barriers
    • Often used to separate computation phases
  • Point-to-point synchronization
    • A process directly notifies another about a certain event on which the latter was waiting
    • Producer-consumer communication pattern
    • Semaphores are used for concurrent programming on uniprocessor through P and V functions
    • Normally implemented through flags on shared memory multiprocessors (busy wait or spin)

    P0: A = 1; flag = 1;
    P1: while (!flag); use (A);