Parallel Programming in Fortran 95 using OpenMP - People
Parallel Programming in Fortran 95 using OpenMP - People
Parallel Programming in Fortran 95 using OpenMP - People
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
4.2. Lock rout<strong>in</strong>es 59<br />
4.2 Lock rout<strong>in</strong>es<br />
The second group of subrout<strong>in</strong>es and functions deal with so called locks. These locks<br />
represent another synchronization mechanism different from the previously presented<br />
<strong>OpenMP</strong> directives like !$OMP ATOMIC or !$OMP CRITICAL.<br />
A lock has to be seen as a flag which can be set or unset. Each thread may look at the<br />
status of the flag and handle <strong>in</strong> one way or the other depend<strong>in</strong>g on the status. Generally,<br />
a thread that looks at an unset flag will set it <strong>in</strong> order to get some privileges and to warn<br />
about that to the rest of the threads. The thread who sets a given lock is said to be<br />
the ownership of the lock. Once the thread no longer needs the acquired privileges, it<br />
unsets the lock: it releases the ownership.<br />
The ma<strong>in</strong> difference between the previously presented synchronization directives and<br />
the locks is that <strong>in</strong> the latter case the threads are not obliged to respect the lock. This<br />
means that a given thread will not be affected by the status of the lock, if the thread is<br />
not tak<strong>in</strong>g care about the status of the lock. Although this seems to be a useless feature,<br />
it turns out to be extremely useful and also very flexible.<br />
To show a possible application of the locks, consider the existence of a shared matrix<br />
A(1:100,1:100) and a parallel region with four threads. Each of the threads needs to<br />
modify values <strong>in</strong> the complete matrix A, but the order does not matter. In order to avoid<br />
race conditions, the follow<strong>in</strong>g solution could be adopted:<br />
!$OMP PARALLEL SHARED(A)<br />
!$OMP CRITICAL<br />
... !works on the matrix A<br />
!$OMP END CRITICAL<br />
!$OMP END PARALLEL<br />
In this example the full matrix A is given to one of the threads while the others are<br />
wait<strong>in</strong>g. This is clearly not a good option. Instead, the matrix could be divided <strong>in</strong>to four<br />
blocks, namely A1 = A(1:50,1:50), A2 = A(51:100,1:50), A3 = A(1:50,51:100) and A4<br />
= A(51:100,51:100). Each of the threads is go<strong>in</strong>g to change values on all four blocks, but<br />
now it seems feasible that each thread gets one of the blocks, thereafter another of the<br />
blocks and so on. In this way rac<strong>in</strong>g conditions are avoided while allow<strong>in</strong>g all the four<br />
threads to work on the matrix A.<br />
This splitt<strong>in</strong>g of the synchronization can be achieved by us<strong>in</strong>g locks, while there is no<br />
means of do<strong>in</strong>g the same us<strong>in</strong>g the previously presented <strong>OpenMP</strong> directives.<br />
The natural sequence of us<strong>in</strong>g locks and the correspond<strong>in</strong>g run-time library rout<strong>in</strong>es<br />
is the follow<strong>in</strong>g one:<br />
1. First, a lock and its associated lock variable (used as identification mechanism <strong>in</strong>side<br />
the program) need to be <strong>in</strong>itialized.<br />
2. Thereafter, a thread gets the ownership of a specified lock.<br />
3. Meanwhile, all the threads potentially affected by the lock look at its state.