Detect OpenMP Races
This tutorial shows how to use Coderrect to detect races in a single file multi-threaded C program written with OpenMP.
Prerequisites
- This tutorial assumes you have successfully installed the Coderrect software following the quick start.
Detect a race in pi.c
We will start by detecting a race in a small single file program pi.c. The program is designed to compute pi=3.1415926…. We provide this example program in the Examples directory under Coderrect installation, or you can copy the code below to your system.
//pi.c #include <omp.h> #include <stdio.h> #define N 1000000000 int main () { double delta = 1.0/(double) N; int MAX_THREADS = omp_get_max_threads(); // Compute parallel compute times for 1-MAX_THREADS for (int j=1; j<= MAX_THREADS; j++) { printf(" running on %d threads: ", j); omp_set_num_threads(j); double sum = 0.0; double start = omp_get_wtime(); #pragma omp parallel for //reduction(+:sum) for (int i=0; i < N; i++) { double x = (i+0.5)*delta; sum += 4.0 / (1.0+x*x); } // Out of the parallel region, finalize computation double pi = delta * sum; double time_lapse = omp_get_wtime() - start; printf("PI = %.12g computed in %.4g secondsn", pi, time_lapse); } }
Check that pi.c can be compiled and run with the following commands
gcc -fopenmp pi.c -o pi ./pi
You should see output that looks something like:
running on 1 threads: PI = 3.141592653589971 computed in 12.84 seconds running on 2 threads: PI = 3.141593993623682 computed in 6.928 seconds running on 3 threads: PI = 3.141594228301372 computed in 7.741 seconds running on 4 threads: PI = 3.141595112697573 computed in 8.376 seconds
As you can see from the results, running on different number of threads generated different values of PI, indicating the existence of a concurrency bug.
Run Coderrect
The easiest way to run the tool is by passing the build command to coderrect:
coderrect -t gcc -fopenmp pi.c
Remember, the command to build pi.c was gcc -fopenmp pi.c.
-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 pi.c should look something like the following:
==== Found a race between: line 22, column 13 in test.c AND line 22, column 17 in test.c Shared variable: at line 16 of test.c 16| double sum = 0.0; Thread 1: 20| for (int i=0; i < N; i++) { 21| double x = (i+0.5)*delta; >22| sum += 4.0 / (1.0+x*x); 23| } 24| >>>Stacktrace: Thread 2: 20| for (int i=0; i < N; i++) { 21| double x = (i+0.5)*delta; >22| sum += 4.0 / (1.0+x*x); 23| } 24| >>>Stacktrace: 1 OpenMP races
Each reported race starts with a summary of where the race was found.
==== Found a race between: line 22, column 13 in test.c AND line 22, column 17 in test.c
Next the report shows the variable name and location on which the race occurs.
Shared variable: at line 16 of test.c 16| double sum = 0.0;
This shows that the race occurs on the variable sum declared on line 16.
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: 20| for (int i=0; i < N; i++) { 21| double x = (i+0.5)*delta; >22| sum += 4.0 / (1.0+x*x); 23| }
The code snippet shows that this racing access is a write to sum as part of an OpenMP parallel for loop.
Taking a closer look at the source code we can see the root cause is the commented out “reduction”.
#pragma omp parallel for //reduction(+:sum)
Un-commenting reduction(+:sum) removes the data race on sum and allows the program to calculate pi correctly.
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 gcc -fopenmp pi.c
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.