Skip to content

CPU 4. Other Parallel Constructs

Phillip Allen Lane edited this page Apr 9, 2024 · 2 revisions

Besides simply creating parallel regions and parallel-for loops, DotMP provides a wide array of constructs that can be used within a parallel region.

Critical Regions

Critical regions are regions of code within a parallel region that should only be executed by a single thread at a time. This provides the primary method for mutual exclusion.

A critical region looks like this:

DotMP.Parallel.Critical(id, () =>
{
    // do mutually exclusive work
});

The id parameter is a limitation of C#, and those coming from OpenMP will notice this change. DotMP requires an id parameter to distinguish between multiple critical regions. If you use the DotMP v2.0 pre-release versions, you do not have to supply an id parameter.

If this is confusing, all you need to know is that each time you write Critical in your code, you should provide it with a unique and constant identifier as the id parameter. This ensures that each critical region is treated as its own individual region.

Barriers

DotMP provides barriers. A barrier in DotMP is a region where:

  1. All threads must reach the barrier before any may proceed (synchronization barrier)
  2. No outstanding memory accesses may be delayed beyond the barrier (memory barrier)

Barriers look like this:

DotMP.Parallel.Barrier();

Master Regions

Master regions are areas of code that are only executed by the master thread (i.e., the thread with an ID of 0). Therefore, only one thread will ever execute code within master regions. A master region looks like this:

DotMP.Parallel.Master(() =>
{
    // thread 0 executes this
});

Single Regions

Single regions are areas of code that are only executed a single time, and by only one thread. Single regions are another worksharing construct. As worksharing constructs cannot be nested, you cannot use a single region within a parallel-for, and you cannot use a parallel-for within a single region.

Single regions look like this:

DotMP.Parallel.Single(id, () =>
{
    // this code is only executed a single time
});

The id parameter works the same as in Parallel.Critical. If you use the DotMP v2.0 pre-release versions, you do not have to supply an id parameter.

Ordered Regions

Ordered regions are areas of code within a parallel-for loop that are executed in-order. These are difficult to explain, so I refer readers to this StackOverflow post.

Ordered regions must be used inside of a parallel-for loop, and look like this:

DotMP.Parallel.Ordered(id, () =>
{
    // do work in-order
});

The id parameter works the same as in Parallel.Critical. If you use the DotMP v2.0 pre-release versions, you do not have to supply an id parameter.

Sections Regions

A DotMP sections region lets you provide a set of delegates to be distributed among threads in a parallel region. It looks like this:

DotMP.Parallel.Sections(() =>
{
    // work item 1
},
() => {
    // work item 2
},
() => {
    // work item 3
},
/* ... */
() => {
    // work item N
});

Each work item is thrown into a central queue, and the parallel region will execute the work items in parallel. Each work item is only executed by a single thread, but many work items can execute simultaneously.

There is also a Parallel.ParallelSections as a wrapper around ParallelRegion and Sections.