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.
- 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 188.8.131.52. 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:
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
This means that thread 0 could be executing
a = a + 1 at the same time thread 1 is running
a = a + 1. Both threads are accessing
a in parallel, causing a data race.
The easiest way to run the tool is by passing the build command to
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.
-t switch is used to generate a quick summary report in terminal.
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
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.
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.
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
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.