0

I'm getting warnings about data races from Thread Sanitizer in this toy example:

#include <vector>
#include <algorithm>
#include <iostream>

int main () {
  std::vector<int> vec(10);

  // increase each vector entry 10 times. Each increment is one task.
#pragma omp parallel
#pragma omp single
  for (int i=0; i < vec.size(); ++i){
    for (int j=0; j < vec.size(); ++j){
#pragma omp task depend(mutexinoutset : vec[i])
      ++vec[i];
    }
  }

  // output as a sanity check
  // expected output: "vec: 10 10 10 10 10 10 10 10 10 10 "
  std::cout << "vec: ";
  std::for_each(vec.begin(), vec.end(), [](auto x) {std::cout << x << " ";});
  std::cout << std::endl;
}

Compiling the code above and executing it via

export TSAN_OPTIONS='ignore_noninstrumented_modules=1'
clang++-15 \
    -g \
    -fopenmp \
    -fno-omit-frame-pointer \
    -fsanitize=thread \
    toyExample.cpp \
    && OMP_NUM_THREADS=8 ./a.out

yields the following error message:

==================
WARNING: ThreadSanitizer: data race (pid=188516)
  Write of size 4 at 0x7f7c50cac568 by main thread:
    #0 .omp_outlined._debug__ /home/seriously/tmp/toyExample.cpp:12 (a.out+0xeab61) (BuildId: 902718ddaac57a371260d1b7f7662a4d9b64a996)
    #1 .omp_outlined..1 /home/seriously/tmp/toyExample.cpp:8 (a.out+0xeae35) (BuildId: 902718ddaac57a371260d1b7f7662a4d9b64a996)
    #2 __kmp_invoke_microtask ??:? (libomp.so+0xcf832) (BuildId: cd83ad3c973e7bba593f306526ed18d28b66ff1e)
    #3 main /home/seriously/tmp/toyExample.cpp:8 (a.out+0xea948) (BuildId: 902718ddaac57a371260d1b7f7662a4d9b64a996)

  Previous read of size 4 at 0x7f7c50cac568 by thread T1:
    #0 .omp_task_entry. /home/seriously/tmp/toyExample.cpp:13 (a.out+0xead8c) (BuildId: 902718ddaac57a371260d1b7f7662a4d9b64a996)
    #1 .omp_task_entry. /home/seriously/tmp/toyExample.cpp:12 (a.out+0xead8c)
    #2 __kmpc_omp_target_task_alloc ??:? (libomp.so+0x68eae) (BuildId: cd83ad3c973e7bba593f306526ed18d28b66ff1e)
    #3 .omp_outlined._debug__ /home/seriously/tmp/toyExample.cpp:9 (a.out+0xeac0f) (BuildId: 902718ddaac57a371260d1b7f7662a4d9b64a996)
    #4 .omp_outlined..1 /home/seriously/tmp/toyExample.cpp:8 (a.out+0xeae35) (BuildId: 902718ddaac57a371260d1b7f7662a4d9b64a996)
    #5 __kmp_invoke_microtask ??:? (libomp.so+0xcf832) (BuildId: cd83ad3c973e7bba593f306526ed18d28b66ff1e)
    #6 main /home/seriously/tmp/toyExample.cpp:8 (a.out+0xea948) (BuildId: 902718ddaac57a371260d1b7f7662a4d9b64a996)

  Location is heap block of size 1048576 at 0x7f7c50bcd000 allocated by main thread:
    #0 malloc ??:? (a.out+0x744e3) (BuildId: 902718ddaac57a371260d1b7f7662a4d9b64a996)
    #1 <null> <null> (libomp.so+0x1fa19) (BuildId: cd83ad3c973e7bba593f306526ed18d28b66ff1e)
    #2 .omp_outlined..1 /home/seriously/tmp/toyExample.cpp:8 (a.out+0xeae35) (BuildId: 902718ddaac57a371260d1b7f7662a4d9b64a996)
    #3 __kmp_invoke_microtask ??:? (libomp.so+0xcf832) (BuildId: cd83ad3c973e7bba593f306526ed18d28b66ff1e)
    #4 main /home/seriously/tmp/toyExample.cpp:8 (a.out+0xea948) (BuildId: 902718ddaac57a371260d1b7f7662a4d9b64a996)

  Thread T1 (tid=188518, running) created by main thread at:
    #0 pthread_create ??:? (a.out+0x68346) (BuildId: 902718ddaac57a371260d1b7f7662a4d9b64a996)
    #1 __kmpc_team_static_init_8u ??:? (libomp.so+0xab437) (BuildId: cd83ad3c973e7bba593f306526ed18d28b66ff1e)

SUMMARY: ThreadSanitizer: data race /home/seriously/tmp/toyExample.cpp:12 in .omp_outlined._debug__
==================
vec: 10 10 10 10 10 10 10 10 10 10 
ThreadSanitizer: reported 1 warnings

The sanity check output is always correct, thus, strongly indicating that this is a false positive. Introducing an actual data race by removing the depend clause immediately affects the sanity check output.

My question is now: Did I misuse OpenMP Tasks or TSan? Or does Tsan simply not support OpenMP explicit tasks?

user17732522
  • 53,019
  • 2
  • 56
  • 105
Seriously
  • 884
  • 1
  • 11
  • 25
  • Did you compile libomp with TSAN instrumentation? – user17732522 Apr 14 '23 at 17:43
  • Tbh I'm not 100% sure. I tested with the repository versions of arch and Ubuntu, which are probably not instrumented. Also I tested a version from a docker container that was compiled with `LIBOMP_OMPT_SUPPORT=ON`. What is the flag I'm looking for? But should that really matter when I use `TSAN_OPTIONS='ignore_noninstrumented_modules=1`? – Seriously Apr 14 '23 at 19:40
  • It seems the TSan annotations for libomp have been removed in LLVM. I don't actually know how it works with the substitute (the "archer.so" OMPT). Maybe you need to set some environment variable to use it? `ignore_noninstrumented_modules` shouldn't matter here I think, since the data race is in instrumented code, but the synchronization in (potentially) non-instrumented code. Ignoring the synchronization wouldn't help. – user17732522 Apr 14 '23 at 20:21

0 Answers0