{"id":4335,"date":"2020-12-13T14:44:03","date_gmt":"2020-12-13T20:44:03","guid":{"rendered":"https:\/\/coderrect.com\/?post_type=docs&p=4335"},"modified":"2021-01-06T15:00:20","modified_gmt":"2021-01-06T21:00:20","slug":"starter-cases","status":"publish","type":"docs","link":"https:\/\/coderrect.com\/docs\/starter-cases\/","title":{"rendered":"Starter Cases"},"content":{"rendered":"\n
This tutorial shows how to use Coderrect to detect races in a single file multi-threaded C program written with OpenMP.<\/p>\n\n\n\n
We will start by detecting a race in a small single file program pi.c<\/strong><\/em>. The program is designed to compute pi=3.1415926\u2026. We provide this example program in the Examples directory under Coderrect installation, or you can copy the code below to your system.<\/p>\n\n\n\n Check that\u00a0pi.c<\/strong><\/em>\u00a0can be compiled and run with the following commands<\/p>\n\n\n\n You should see output that looks something like:<\/p>\n\n\n\n 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.<\/p>\n\n\n\n The easiest way to run the tool is by passing the build command to\u00a0coderrect<\/strong><\/em>:<\/p>\n\n\n\n Remember, the command to build pi.c was\u00a0gcc -fopenmp pi.c<\/strong><\/em>.<\/p>\n\n\n\n -t switch is used to generate a quick summary report in terminal.<\/p>\n\n\n\n Calling\u00a0coderrect\u00a0<\/strong><\/em>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\u00a0make<\/a>,\u00a0coderrect\u00a0<\/em><\/strong>tool can be called with the same build command used to build the project. For an example: checkout out\u00a0detecting races in a Makefile-based project.<\/p>\n\n\n\n The\u00a0coderrect<\/em><\/strong>\u00a0tool 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.<\/p>\n\n\n\n The terminal report for pi.c should look something like the following:<\/p>\n\n\n\n Each reported race starts with a summary of where the race was found.<\/p>\n\n\n\n Next the report shows the variable name and location on which the race occurs.<\/p>\n\n\n\n This shows that the race occurs on the variable\u00a0sum\u00a0<\/em><\/strong>declared on line 16.<\/p>\n\n\n\n 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.<\/p>\n\n\n\n The code snippet shows that this racing access is a write to\u00a0sum\u00a0<\/em><\/strong>as part of an OpenMP parallel for loop.<\/p>\n\n\n\n Taking a closer look at the source code we can see the root cause is the commented out \u201creduction\u201d.\u00a0<\/p>\n\n\n\n Un-commenting\u00a0reduction(+:sum)<\/em><\/strong>\u00a0removes the data race on\u00a0sum\u00a0<\/em><\/strong>and allows the program to calculate pi correctly.<\/p>\n\n\n\n The terminal is great to get a quick idea about what races are reported, but the full report can be viewed in a browser.<\/p>\n\n\n\n We can also save the race report to a directory specified via the command option-o <dir>.<\/em><\/strong>\u00a0<\/p>\n\n\n\n This created a directory named\u00a0report\u00a0<\/strong><\/em>and a file named\u00a0index.html<\/strong><\/em>\u00a0within that directory. To view the full report open the\u00a0index.html<\/em><\/strong>\u00a0file in a browser.<\/p>\n\n\n\n This tutorial shows how to use Coderrect to detect races in a single file multi-threaded C++ program written with the\u00a0POSIX threads<\/a>\u00a0(Pthreads) library.<\/p>\n\n\n\n This tutorial assumes you have successfully installed the Coderrect software following the quick start<\/a>.<\/p>\n\n\n\n Our sample code Copy the source for pthread-test.cc below to your system.<\/p>\n\n\n\n Check that\u00a0 If run\u00a0 The easiest way to get started on a single file is to run<\/p>\n\n\n\n -t switch is used to generate a quick summary report in terminal, for more information on Coderrect configurations, please check out reference page<\/a>.<\/p>\n\n\n\n This will automatically detect the races and report the follow in the terminal:<\/p>\n\n\n\n Each reported race starts with a summary of where the race was found.<\/p>\n\n\n\n Next the report shows the name and location of the variable on which the race occurs.<\/p>\n\n\n\n This shows that the race occurs on the variable\u00a0x\u00a0<\/em><\/strong>declared on line 7.<\/p>\n\n\n\n Next the tool reports information about the two unsynchronized accesses to\u00a0x<\/em><\/strong>. The location shows the file, line, and column of the access.<\/p>\n\n\n\n So the above access occurs in pthread-race.cc at line 12 column 5 and at line 38 column 41, respectively.<\/p>\n\n\n\n Going and finding this location in the code may be a little tedious so the report also shows a preview of the file at that location.<\/p>\n\n\n\n The code snippet shows that this access is an unsynchronized write to\u00a0x<\/em><\/strong>\u00a0in each child thread.<\/p>\n\n\n\n The last piece of information shown for each access is the stack trace.<\/p>\n\n\n\n The stack trace shows the call stack under which the racing access occurred. In the example above the stack trace shows\u00a0PrintHello\u00a0<\/strong><\/em>being called from line 20 in\u00a0pthread-race.cc<\/strong><\/em>.<\/p>\n\n\n\n The full report can be viewed in a browser.<\/p>\n\n\n\n This tutorial showcases Coderrect on detecting block-level and warp-level race hazards in GPU\/CUDA kernels. Both examples are from NVIDIA\u2019s official documentation:\u00a0block_error.cu<\/a>\u00a0and\u00a0warp_error.cu<\/a>. Note that if you do not already have nvidia-cuda-toolkit installed on your machine you must use the command listed below.<\/p>\n\n\n\n Note that in the above code line 13 is commented out, which disables the warp-level synchronization.\u00a0<\/p>\n\n\n\n If line 13 is uncommented, the race will be fixed, and the tool will report no races:\u00a0<\/p>\n\n\n\n This tutorial shows how to use Coderrect to detect races in a Makefile-based project using\u00a0pbzip2-0.9.4<\/a>\u00a0as the example. pbzip2 is a parallel implementation of the\u00a0bzip2 file compressor<\/a>, and it contains a known race condition in version 0.9.4.<\/p>\n\n\n\n This tutorial assumes you have successfully installed the Coderrect software following the quick start<\/a>.<\/p>\n\n\n\n In pbzip2, the program will spawn consumer threads that (de)compress the input file and spawn an output thread that writes data to the output file. However, the main thread only joins the output thread but does not join the consumer threads. So there is an order violation bug between the time when the main thread is destroying resources and the time when consumer threads are using the resources.<\/p>\n\n\n\n An interleaving that triggers the error looks like:<\/p>\n\n\n\n Since\u00a0queueDelete\u00a0<\/em><\/strong>will release the\u00a0fifo\u00a0<\/strong><\/em>queue used by consumer threads, the access on\u00a0fifo->mut<\/em><\/strong>\u00a0will result in a segmentation fault.<\/p>\n\n\n\n Make sure the code can be compiled<\/p>\n\n\n\n You should see a\u00a0pbzip2\u00a0<\/em><\/strong>executable under the same folder.<\/p>\n\n\n\n NOTE:\u00a0<\/strong>The\u00a0make clean<\/em><\/strong>\u00a0command is to ensure there is no pre-built binaries so that Coderrect is able to analyze every piece of source code in the project.<\/p>\n\n\n\n The\u00a0coderrect -t -o report make<\/em><\/strong>\u00a0command will compile and analyze the problem, the reported races is stored under\u00a0.\/report<\/em><\/strong>\u00a0directory as specified by\u00a0-o<\/em><\/strong>\u00a0option.<\/p>\n\n\n\n -t switch is used to generate a quick summary report in terminal.<\/p>\n\n\n\n The\u00a0coderrect\u00a0<\/em><\/strong>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 the browser.<\/p>\n\n\n\n The terminal races reports looks like following:<\/p>\n\n\n\n Each reported race starts with a summary of where the race was found.<\/p>\n\n\n\n Next the report shows the name and location of the variable on which the race occurs.<\/p>\n\n\n\n This shows that the race occurs on the variable\u00a0queue\u00a0<\/em><\/strong>allocated at line 991.<\/p>\n\n\n\n Next the tool reports information about the two unsynchronized accesses to\u00a0queue<\/em><\/strong>. The location shows the file, line, and column of the access.<\/p>\n\n\n\n So the above access occurs in pbzip2.cpp at line 1048 column 3. The code snippet shows that this access is a write to\u00a0q->mut<\/em><\/strong>\u00a0(set it to NULL).<\/p>\n\n\n\n The terminal is great to get a quick idea about what races are reported, but the full report can be viewed in a browser.<\/p>\n\n\n\n This tutorial shows how to use Coderrect to detect races in a single file multi-threaded Fortran program written with OpenMP.<\/p>\n\n\n\n We will be using a benchmark from DataRaceBench<\/a>, 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<\/a>. DataRaceBench is full of great test cases (try using it to evaluate coderrect!).<\/p>\n\n\n\n We will be using the\u00a0DRB001-antidep1-orig-yes.f95<\/a>\u00a0case from\u00a0DataRaceBench version 1.3.0.1<\/a>. You can get the source code from the DataRaceBench repository on github, but we have included a snippet here for convenience.<\/p>\n\n\n\n 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\u2019s analysis. The DRB001 benchmark can be built with the following command<\/p>\n\n\n\n You should see output that looks something like:<\/p>\n\n\n\n Although your results may vary because there is a data race in this code. In the parallel for loop, the value of each iteration\u00a0i\u00a0<\/em><\/strong>depends on the next iteration\u00a0i+1<\/strong><\/em>.<\/p>\n\n\n\n This means that thread 0 could be executing\u00a0a[0] = a[1] + 1<\/em><\/strong>\u00a0at the same time thread 1 is running\u00a0a[1] = a[2] + 1<\/strong><\/em>. Both threads are accessing\u00a0a[1]<\/em><\/strong>\u00a0in parallel, causing a data race.<\/p>\n\n\n\n The easiest way to run the tool is by passing the build command to\u00a0coderrect<\/em><\/strong>:<\/p>\n\n\n\n Remember, the command to build DRB001 was\u00a0gfortran -fopenmp DRB001-antidep1-orig-yes.f95 -o DRB001<\/em><\/strong>.<\/p>\n\n\n\n the\u00a0-t\u00a0<\/em><\/strong>switch is used to generate a quick summary report in terminal.<\/p>\n\n\n\n Calling\u00a0coderrect<\/em><\/strong>\u00a0in this way ensures all the required compilation flags can be passed on the command line. For a project using a build system such as\u00a0make<\/a>,\u00a0coderrect\u00a0<\/em><\/strong>tool can be called with the same build command used to build the project. For an example: checkout out\u00a0detecting races in a Makefile-based project<\/a>.<\/p>\n\n\n\n The\u00a0coderrect\u00a0<\/em><\/strong>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.<\/p>\n\n\n\n The terminal report for DRB001 should look something like the following:<\/p>\n\n\n\n Each reported race starts with a summary of where the race was found.<\/p>\n\n\n\n Next the report shows the variable name and location on which the race occurs. (Though this is sometimes not present for fortran programs)<\/p>\n\n\n\n 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.<\/p>\n\n\n\n The code snippet shows that this racing access is a write to\u00a0a(i)<\/em><\/strong>\u00a0as part of an OpenMP parallel for loop.<\/p>\n\n\n\n\/\/pi.c\n#include <omp.h>\n#include <stdio.h>\n\n#define N 1000000000\n\nint main () {\n\n double delta = 1.0\/(double) N;\n int MAX_THREADS = omp_get_max_threads();\n \/\/ Compute parallel compute times for 1-MAX_THREADS\n for (int j=1; j<= MAX_THREADS; j++) {\n\n printf(\" running on %d threads: \", j);\n omp_set_num_threads(j);\n\n double sum = 0.0;\n double start = omp_get_wtime();\n\n #pragma omp parallel for \/\/reduction(+:sum)\n for (int i=0; i < N; i++) {\n double x = (i+0.5)*delta;\n sum += 4.0 \/ (1.0+x*x);\n }\n\n \/\/ Out of the parallel region, finalize computation\n double pi = delta * sum;\n double time_lapse = omp_get_wtime() - start;\n printf(\"PI = %.12g computed in %.4g secondsn\", pi, time_lapse);\n }\n}<\/pre>\n\n\n\n
gcc -fopenmp pi.c -o pi\n.\/pi<\/pre>\n\n\n\n
running on 1 threads: PI = 3.141592653589971 computed in 12.84 seconds\nrunning on 2 threads: PI = 3.141593993623682 computed in 6.928 seconds\nrunning on 3 threads: PI = 3.141594228301372 computed in 7.741 seconds\nrunning on 4 threads: PI = 3.141595112697573 computed in 8.376 seconds<\/pre>\n\n\n\n
\n\n\n\nRun Coderrect<\/h3>\n\n\n\n
coderrect -t gcc -fopenmp pi.c<\/pre>\n\n\n\n
\n\n\n\nInterpret the Results<\/h3>\n\n\n\n
\n\n\n\nTerminal Report<\/h4>\n\n\n\n
==== Found a race between: \nline 22, column 13 in test.c AND line 22, column 17 in test.c\nShared variable:\n at line 16 of test.c\n 16| double sum = 0.0;\nThread 1:\n 20| for (int i=0; i < N; i++) {\n 21| double x = (i+0.5)*delta;\n>22| sum += 4.0 \/ (1.0+x*x);\n 23| }\n 24|\n>>>Stacktrace:\nThread 2:\n 20| for (int i=0; i < N; i++) {\n 21| double x = (i+0.5)*delta;\n>22| sum += 4.0 \/ (1.0+x*x);\n 23| }\n 24|\n>>>Stacktrace:\n\n 1 OpenMP races<\/pre>\n\n\n\n
==== Found a race between: \nline 22, column 13 in test.c AND line 22, column 17 in test.c<\/pre>\n\n\n\n
Shared variable:\n at line 16 of test.c\n 16| double sum = 0.0;<\/pre>\n\n\n\n
Thread 1:\n 20| for (int i=0; i < N; i++) {\n 21| double x = (i+0.5)*delta;\n>22| sum += 4.0 \/ (1.0+x*x);\n 23| }<\/pre>\n\n\n\n
#pragma omp parallel for \/\/reduction(+:sum)<\/pre>\n\n\n\n
\n\n\n\nHTML Report<\/h4>\n\n\n\n
coderrect -o report gcc -fopenmp pi.c<\/pre>\n\n\n\n
\n\n\n\nDetect pthread races<\/h2>\n\n\n\n
coderrect g++ pthread-race.cc -lpthread<\/pre>\n\n\n\n
\n\n\n\nPrerequisites<\/h3>\n\n\n\n
Detecting races in pthread-race.cc<\/h3>\n\n\n\n
pthread-race.cc<\/code> starts two children threads in the main method. Each child thread increments a shared variable \u201cx\u201d by one, but there is a race.<\/p>\n\n\n\n
#include <pthread.h>\n\n#include <cstdlib>\n#include <iostream>\n\nusing namespace std;\nint x = 0;\n\nvoid *PrintHello(void *threadid) {\n long tid;\n tid = (long)threadid;\n x++;\n cout << \"Hello World! Thread ID, \" << tid << endl;\n pthread_exit(NULL);\n}\n\npthread_t load_data_in_thread(long id) {\n pthread_t thread;\n void *arg = (void *)id;\n int rc = pthread_create(&thread, NULL, PrintHello, arg);\n if (rc) {\n cout << \"Error:unable to create thread,\" << rc << endl;\n exit(-1);\n }\n return thread;\n}\n\nint main() {\n pthread_t thread1, thread2;\n\n cout << \"main() : creating thread 1 \" << endl;\n thread1 = load_data_in_thread(1);\n cout << \"main() : creating thread 2 \" << endl;\n thread2 = load_data_in_thread(2);\n pthread_join(thread1, 0);\n \/\/ pthread_join(thread2,0);\n cout << \"Final value of x: \" << x << endl;\n}<\/pre>\n\n\n\n
pthread-race.cc<\/code>\u00a0can be compiled and run with the following commands<\/p>\n\n\n\n
g++ pthread-race.cc -lpthread\n.\/a.out<\/pre>\n\n\n\n
.\/a.out<\/code>\u00a0multiple times, you should see output that looks something like:<\/p>\n\n\n\n
main() : creating thread 1 \nmain() : creating thread 2 \nHello World! Thread ID, 1\nFinal value of x: 1\nHello World! Thread ID, 2<\/pre>\n\n\n\n
\n\n\n\nRun Coderrect<\/h3>\n\n\n\n
coderrect -t g++ pthread-race.cc -lpthread<\/pre>\n\n\n\n
==== Found a race between: \nline 12, column 5 in pthread-race.cc AND line 38, column 41 in pthread-race.cc\nShared variable: \n at line 7 of pthread-race.cc\n 7|int x =0;\nThread 1: \npthread-race.cc@12:5\nCode snippet: \n 10| long tid;\n 11| tid = (long)threadid;\n>12| x++;\n 13| cout << \"Hello World! Thread ID, \" << tid << endl;\n 14| pthread_exit(NULL);\n>>>Stack Trace:\n>>>PrintHello(void*) [pthread-race.cc:20]\nThread 2: \npthread-race.cc@38:41\nCode snippet: \n 36| \/\/pthread_join(thread2,0);\n 37|\n>38| cout << \"Final value of x: \" << x << endl;\n 39|}\n>>>Stack Trace:\n>>>main()\n>>> std::basic_ostream<char, std::char_traits<char> >& std::operator<<<std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) [pthread-race.cc:38]\n>>> std::char_traits<char>::length(char const*) [\/usr\/lib\/gcc\/x86_64-linux-gnu\/7.4.0\/..\/..\/..\/..\/include\/c++\/7.4.0\/ostream:562]\ndetected 1 races in total.\n\n2020\/02\/25 01:18:23 Generating the race report ...\nTo check the race report, please open '.\/index.html' in your browser<\/pre>\n\n\n\n
\n\n\n\nInterpret the Results<\/h3>\n\n\n\n
==== Found a race between: \nline 12, column 5 in pthread-race.cc AND line 38, column 41 in pthread-race.cc<\/pre>\n\n\n\n
Shared variable: \n at line 7 of pthread-race.cc\n 7|int x =0;<\/pre>\n\n\n\n
For each of the two accesses a location, code snippet, and stack trace is shown.<\/p>\n\n\n\npthread-race.cc@12:5\npthread-race.cc@38:41<\/pre>\n\n\n\n
Code snippet: \n 10| long tid;\n 11| tid = (long)threadid;\n>12| x++;\n 13| cout << \"Hello World! Thread ID, \" << tid << endl;\n 14| pthread_exit(NULL);<\/pre>\n\n\n\n
>>>Stack Trace:\n>>>PrintHello(void*) [pthread-race.cc:20]\n\n>>>main()\n>>> std::basic_ostream<char, std::char_traits<char> >& std::operator<<<std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) [pthread-race.cc:38]\n>>> std::char_traits<char>::length(char const*) [\/usr\/lib\/gcc\/x86_64-linux-gnu\/7.4.0\/..\/..\/..\/..\/include\/c++\/7.4.0\/ostream:562]<\/pre>\n\n\n\n
Each line in the call stack shows the name of the function, and the location the function was called from.<\/p>\n\n\n\n
\n\n\n\nHTML Report<\/h3>\n\n\n\n
\n\n\n\nDetect races in GPU kernels<\/h2>\n\n\n\n
$ sudo apt install nvidia-cuda-toolkit\n$ coderrect -t nvcc block_error.cu<\/pre>\n\n\n\n
==== Found a race between: \nline 9, column 5 in block_error.cu AND line 14, column 25 in block_error.cu\nShared variable: \nsmem at line 3 of block_error.cu\n 3|__shared__ int smem[THREADS];\nThread 1: \n 7|{\n 8| int tx = threadIdx.x;\n>9| smem[tx] = data_in[tx] + tx;\n 10|\n 11| if (tx == 0) {\n>>>Stack Trace:\nThread 2: \n 12| *sum_out = 0;\n 13| for (int i = 0; i < THREADS; ++i)\n>14| *sum_out += smem[i];\n 15| }\n 16|}\n>>>Stack Trace:\nThe OpenMP region this bug occurs:\n\/CUDA\/benchmarks\/t\/block_error.cu\n>27| sumKernel<<<1, THREADS>>>(data_in, sum_out);\n 28| cudaDeviceSynchronize();\n 29|\n 30| cudaFree(data_in);\n 31| cudaFree(sum_out);\n 32| return 0;\nGets called from:\n>>>main\ndetected 1 races in total.\nTo check the race report, please open '\/CUDA\/benchmarks\/t\/.coderrect\/report\/index.html' in your browser<\/pre>\n\n\n\n
\n\n\n\n$ coderrect -t nvcc wrap_error.cu<\/pre>\n\n\n\n
==== Found a race between: \nline 12, column 5 in wrap_error.cu AND line 19, column 32 in wrap_error.cu\nShared variable: \nsmem_first at line 5 of wrap_error.cu\n 5|__shared__ int smem_first[THREADS];\nThread 1: \n 10|{\n 11| int tx = threadIdx.x;\n>12| smem_first[tx] = data_in[tx] + tx;\n 13| \/\/__syncwarp();\n 14| if (tx % WARP_SIZE == 0) {\n>>>Stack Trace:\nThread 2: \n 17| smem_second[wx] = 0;\n 18| for (int i = 0; i < WARP_SIZE; ++i)\n>19| smem_second[wx] += smem_first[wx * WARP_SIZE + i];\n 20| }\n 21|\n>>>Stack Trace:\nThe OpenMP region this bug occurs:\n\/CUDA\/benchmarks\/t\/wrap_error.cu\n>40| sumKernel<<<1, THREADS>>>(data_in, sum_out);\n 41| cudaDeviceSynchronize();\n 42|\n 43| cudaFree(data_in);\n 44| cudaFree(sum_out);\n 45| return 0;<\/pre>\n\n\n\n
13| \/\/__syncwarp();<\/pre>\n\n\n\n
detected 0 races in total.<\/pre>\n\n\n\n
\n\n\n\nDetect races in a Makefile-based project<\/h2>\n\n\n\n
git clone https:\/\/github.com\/sctbenchmarks\/sctbenchmarks.git\ncd sctbenchmarks\/1CB-0-2\/pbzip2-0.9.4\/bzip2-1.0.6\nmake clean\nmake\ncd ..\ncd pbzip2-0.9.4\nmake clean\ncoderrect make<\/pre>\n\n\n\n
\n\n\n\nPrerequisites<\/h3>\n\n\n\n
\n\n\n\nBackground<\/h3>\n\n\n\n
void main(...) { \n ...\n for (i=0; i < numCPU; i++) { \n ret = pthread_create(..., consumer, \n fifo); \n ... \n }\n ret = pthread_create(..., fileWriter, \n OutFilename);\n ...\n \/\/ start reading in data\n producer(..., fifo);\n ...\n \/\/ wait until exit of thread\n pthread_join(output, NULL);\n ...\n fifo->empty = 1;\n ...\n \/\/ reclaim memory\n queueDelete(fifo);\n fifo = NULL;\n\n\n\n}<\/pre>\n\n\n\n
void *decompress_consumer(void *q) {\n ...\n for (;;) {\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n pthread_mutex_lock(fifo->mut);\n ...\n }\n}<\/pre>\n\n\n\n
\n\n\n\nDetect the race using Coderrect<\/h3>\n\n\n\n
cd sctbenchmarks\/1CB-0-2\/pbzip2-0.9.4\/pbzip2-0.9.4\nmake<\/pre>\n\n\n\n
\n\n\n\nRun Coderrect<\/h3>\n\n\n\n
make clean \ncoderrect -t -o report make<\/pre>\n\n\n\n
\n\n\n\nInterpret the Results<\/h3>\n\n\n\n
Terminal Report<\/h3>\n\n\n\n
==== Found a race between: \nline 1048, column 3 in pbzip2.cpp AND line 553, column 28 in pbzip2.cpp\nShared variable: \n at line 991 of pbzip2.cpp\n 991| q = new queue;\nThread 1: \npbzip2.cpp@1048:3\nCode snippet: \n 1046| pthread_mutex_destroy(q->mut);\n 1047| delete q->mut;\n>1048| q->mut = NULL;\n 1049| }\n 1050|\n>>>Stack Trace:\n>>>main\n>>> queueDelete(queue*) [pbzip2.cpp:1912]\nThread 2: \npbzip2.cpp@553:28\nCode snippet: \n 551| for (;;)\n 552| {\n>553| pthread_mutex_lock(fifo->mut);\n 554| while (fifo->empty)\n 555| {\n>>>Stack Trace:\n>>>pthread_create [pbzip2.cpp:1818]\n>>> consumer_decompress(void*) [pbzip2.cpp:1818]<\/pre>\n\n\n\n
==== Found a race between: \nline 1048, column 3 in pbzip2.cpp AND line 553, column 28 in pbzip2.cpp<\/pre>\n\n\n\n
Shared variable: \n at line 991 of pbzip2.cpp\n 991| q = new queue;<\/pre>\n\n\n\n
For each of the two accesses a location, code snippet, and stack trace is shown.<\/p>\n\n\n\nThread 1: \npbzip2.cpp@1048:3<\/pre>\n\n\n\n
The report also shows a preview of the file at that location.<\/p>\n\n\n\nCode snippet: \n 1046| pthread_mutex_destroy(q->mut);\n 1047| delete q->mut;\n>1048| q->mut = NULL;\n 1049| }\n 1050|<\/pre>\n\n\n\n
HTML Report<\/h3>\n\n\n\n
\n\n\n\nDetect Fortran OpenMP Races<\/h2>\n\n\n\n
\n\n\n\nPrerequisites<\/h3>\n\n\n\n
\n\n\n\nDetecting a race<\/h3>\n\n\n\n
!!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!\n!!! Copyright (c) 2017-20, Lawrence Livermore National Security, LLC\n!!! and DataRaceBench project contributors. See the DataRaceBench\/COPYRIGHT file for details.\n!!!\n!!! SPDX-License-Identifier: (BSD-3-Clause)\n!!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!\n\n!A loop with loop-carried anti-dependence.\n!Data race pair: a[i+1]@25:9 vs. a[i]@25:16\n\nprogram DRB001_antidep1_orig_yes\nuse omp_lib\n implicit none\n integer :: i, len\n integer :: a(1000)\n\n len = 1000\n\n do i = 1, len\n a(i) = i\n end do\n\n !$omp parallel do\n do i = 1, len-1\n a(i) = a(i+1) + 1\n end do\n !$omp end parallel do\n\n print 100, a(500)\n 100 format ('a(500)=',i3)\nend program\n<\/pre>\n\n\n\n
gfortran -fopenmp DRB001-antidep1-orig-yes.f95 -o DRB001\n.\/DRB001<\/pre>\n\n\n\n
a(500)=502<\/pre>\n\n\n\n
\n\n\n\nRun Coderrect<\/h3>\n\n\n\n
coderrect -t gfortran -fopenmp DRB001-antidep1-orig-yes.f95 -o DRB001<\/pre>\n\n\n\n
\n\n\n\nInterpret the Results<\/h3>\n\n\n\n
Terminal Report<\/h3>\n\n\n\n
==== Found a data race between: \nline 25, column 0 in DRB001-antidep1-orig-yes.f95 AND line 25, column 1 in DRB001-antidep1-orig-yes.f95\nShared variable:\n at line 0 of \n 0|\nThread 1:\n 23| !$omp parallel do\n 24| do i = 1, len-1\n>25| a(i) = a(i+1) + 1\n 26| end do\n 27| !$omp end parallel do\n>>>Stacktrace:\nThread 2:\n 23| !$omp parallel do\n 24| do i = 1, len-1\n>25| a(i) = a(i+1) + 1\n 26| end do\n 27| !$omp end parallel do\n>>>Stacktrace:<\/pre>\n\n\n\n
==== Found a race between: \nline 25, column 0 in DRB001-antidep1-orig-yes.f95 AND line 25, column 1 in DRB001-antidep1-orig-yes.f95<\/pre>\n\n\n\n
Shared variable:\n ...<\/pre>\n\n\n\n
Thread 1:\n 23| !$omp parallel do\n 24| do i = 1, len-1\n>25| a(i) = a(i+1) + 1\n 26| end do\n 27| !$omp end parallel do<\/pre>\n\n\n\n