Detect Fortran OpenMP Races
This tutorial shows how to use Coderrect to detect races in a single file multi-threaded Fortran program written with OpenMP.
Prerequisites
- This tutorial assumes you have successfully installed the Coderrect software following the quick start.
Detecting a race
We will be using a benchmark from DataRaceBench, a suite of OpenMP data race benchmarks designed to evaluate the effectiveness of data race detection tools developed by a group at Lawrence Livermore National Lab. DataRaceBench is full of great test cases (try using it to evaluate coderrect!).
We will be using the DRB001-antidep1-orig-yes.f95 case from DataRaceBench version 1.3.0.1. You can get the source code from the DataRaceBench repository on github, but we have included a snippet here for convenience.
!!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!
!!! Copyright (c) 2017-20, Lawrence Livermore National Security, LLC
!!! and DataRaceBench project contributors. See the DataRaceBench/COPYRIGHT file for details.
!!!
!!! SPDX-License-Identifier: (BSD-3-Clause)
!!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!
!A loop with loop-carried anti-dependence.
!Data race pair: a[i+1]@25:9 vs. a[i]@25:16
program DRB001_antidep1_orig_yes
use omp_lib
implicit none
integer :: i, len
integer :: a(1000)
len = 1000
do i = 1, len
a(i) = i
end do
!$omp parallel do
do i = 1, len-1
a(i) = a(i+1) + 1
end do
!$omp end parallel do
print 100, a(500)
100 format ('a(500)=',i3)
end program
Start by checking that the program compiles successfully on your machine. Coderrect works by intercepting compiler calls. If the code cannot be compiled, Coderrect cannot run it’s analysis. The DRB001 benchmark can be built with the following command
gfortran -fopenmp DRB001-antidep1-orig-yes.f95 -o DRB001
./DRB001
You should see output that looks something like:
a(500)=502
Although your results may vary because there is a data race in this code. In the parallel for loop, the value of each iteration i
depends on the next iteration i+1
.
This means that thread 0 could be executing a[0] = a[1] + 1
at the same time thread 1 is running a[1] = a[2] + 1
. Both threads are accessing a[1]
in parallel, causing a data race.
Run Coderrect
The easiest way to run the tool is by passing the build command to coderrect
:
coderrect -t gfortran -fopenmp DRB001-antidep1-orig-yes.f95 -o DRB001
Remember, the command to build DRB001 was gfortran -fopenmp DRB001-antidep1-orig-yes.f95 -o DRB001
.
the -t
switch is used to generate a quick summary report in terminal.
Calling coderrect
in this way ensures all the required compilation flags can be passed on the command line. For a project using a build system such as make, coderrect
tool can be called with the same build command used to build the project. For an example: checkout out detecting races in a Makefile-based project.
Interpret the Results
The coderrect
tool reports a quick summary of the most interesting races directly in the terminal for quick viewing. The tool also generates a more comprehensive report that can be viewed in a browser.
Terminal Report
The terminal report for DRB001 should look something like the following:
==== Found a data race between:
line 25, column 0 in DRB001-antidep1-orig-yes.f95 AND line 25, column 1 in DRB001-antidep1-orig-yes.f95
Shared variable:
at line 0 of
0|
Thread 1:
23| !$omp parallel do
24| do i = 1, len-1
>25| a(i) = a(i+1) + 1
26| end do
27| !$omp end parallel do
>>>Stacktrace:
Thread 2:
23| !$omp parallel do
24| do i = 1, len-1
>25| a(i) = a(i+1) + 1
26| end do
27| !$omp end parallel do
>>>Stacktrace:
Each reported race starts with a summary of where the race was found.
==== Found a race between:
line 25, column 0 in DRB001-antidep1-orig-yes.f95 AND line 25, column 1 in DRB001-antidep1-orig-yes.f95
Next the report shows the variable name and location on which the race occurs. (Though this is sometimes not present for fortran programs)
Shared variable:
...
Going and finding the race location in the code may be a little tedious so the report also shows a preview of the file at that location.
Thread 1:
23| !$omp parallel do
24| do i = 1, len-1
>25| a(i) = a(i+1) + 1
26| end do
27| !$omp end parallel do
The code snippet shows that this racing access is a write to a(i)
as part of an OpenMP parallel for loop.
This is the race we expected to find for this DataRaceBench case. You can try running coderrect in the same way on the other DataRaceBench fortran benchmarks at dataracebench/micro-benchmarks-fortran.
HTML Report
The terminal is great to get a quick idea about what races are reported, but the full report can be viewed in a browser.
We can also save the race report to a directory specified via the command option-o <dir>
.
coderrect -o report gfortran -fopenmp DRB001-antidep1-orig-yes.f95 -o DRB001
This created a directory named report
and a file named index.html
within that directory. To view the full report open the index.html
file in a browser.