Состояние гонки в OpenMP вне параллельного блока (ThreadSanitizer); ложный положительный результат? - PullRequest
0 голосов
/ 26 января 2020

Следующий минимальный пример вычисляет сумму всех чисел от 1 до 1000 и распараллеливается с OpenMP:

#include <iostream>

double sum;

void do_it() {
  const size_t n = 1000;
#pragma omp parallel
  {
#pragma omp for
    for (size_t i = 1; i <= n; ++i) {
#pragma omp atomic
      sum += static_cast<double>(i);
    }
  }
}

int main() {
  sum = 0.;
  do_it();
  std::cout << sum << std::endl;
  return 0;
}

Я попытался скомпилировать это либо с clang++-6.0.0 и g++-5.4.0 и ThreadSanitizer. Оба компилятора выдают несколько предупреждений об условиях гонки в libomp.so / libgomp.so, которые, как я предполагаю, являются ложными срабатываниями, и следующее предупреждение о моем коде:

==================
WARNING: ThreadSanitizer: data race (pid=22081)
  Read of size 8 at 0x000001555f48 by main thread:
    #0 main /home/arekfu/src/foo/openmp.cc:20 (openmp+0x4be0ce)

  Previous atomic write of size 8 at 0x000001555f48 by thread T11:
    #0 __tsan_atomic64_compare_exchange_val ??:? (openmp+0x476470)
    #1 .omp_outlined._debug__ /home/arekfu/src/foo/openmp.cc:12 (openmp+0x4be011)
    #2 .omp_outlined. /home/arekfu/src/foo/openmp.cc:8 (openmp+0x4be011)
    #3 __kmp_invoke_microtask ??:? (libomp.so.5+0x994b2)

  Location is global '<null>' at 0x000000000000 (openmp+0x000001555f48)

  Thread T11 (tid=22093, running) created by main thread at:
    #0 pthread_create ??:? (openmp+0x4284db)
    #1 __kmpc_threadprivate_register_vec ??:? (libomp.so.5+0x5bc1f)
    #2 __libc_start_main /build/glibc-LK5gWL/glibc-2.23/csu/../csu/libc-start.c:291 (libc.so.6+0x2082f)

SUMMARY: ThreadSanitizer: data race /home/arekfu/src/foo/openmp.cc:20 in main
==================

Я не вижу никакой гонки данных в хотя мой код!

Я также пытался заменить atomic обновления на раздел critical, например:

#pragma omp critical
      {
        sum += static_cast<double>(i);
      }

Это меняет предупреждение, но новое не делает имеет гораздо больше смысла:

==================
WARNING: ThreadSanitizer: data race (pid=27477)
  Write of size 8 at 0x000001555f48 by thread T4:
    #0 .omp_outlined._debug__ /home/arekfu/src/foo/openmp.cc:13 (openmp+0x4be0a2)
    #1 .omp_outlined. /home/arekfu/src/foo/openmp.cc:8 (openmp+0x4be0a2)
    #2 __kmp_invoke_microtask ??:? (libomp.so.5+0x994b2)

  Previous write of size 8 at 0x000001555f48 by thread T3:
    #0 .omp_outlined._debug__ /home/arekfu/src/foo/openmp.cc:13 (openmp+0x4be0a2)
    #1 .omp_outlined. /home/arekfu/src/foo/openmp.cc:8 (openmp+0x4be0a2)
    #2 __kmp_invoke_microtask ??:? (libomp.so.5+0x994b2)

  Location is global '<null>' at 0x000000000000 (openmp+0x000001555f48)

  Thread T4 (tid=27482, running) created by main thread at:
    #0 pthread_create ??:? (openmp+0x42857b)
    #1 __kmpc_threadprivate_register_vec ??:? (libomp.so.5+0x5bc1f)
    #2 __libc_start_main /build/glibc-LK5gWL/glibc-2.23/csu/../csu/libc-start.c:291 (libc.so.6+0x2082f)

  Thread T3 (tid=27481, running) created by main thread at:
    #0 pthread_create ??:? (openmp+0x42857b)
    #1 __kmpc_threadprivate_register_vec ??:? (libomp.so.5+0x5bc1f)
    #2 __libc_start_main /build/glibc-LK5gWL/glibc-2.23/csu/../csu/libc-start.c:291 (libc.so.6+0x2082f)

SUMMARY: ThreadSanitizer: data race /home/arekfu/src/foo/openmp.cc:13 in .omp_outlined._debug__
==================

Являются ли эти предупреждения указанием на реальные расы данных или ложными срабатываниями?

1 Ответ

0 голосов
/ 27 января 2020

«Проблема» - это операция чтения суммы в строке 20:

std::cout << sum << std::endl; // here you are reading the value of sum

TSAN не может определить межпотоковую связь до того, как произойдет связь между этим чтением и обновлениями (atomi c) в Л oop. Но, конечно, такая связь существует, поскольку все потоки синхронизируются в конце блока omp. Так что да, это ложное срабатывание.

В этом посте содержится дополнительная информация о том, как избежать ложных срабатываний с OpenMP: Можно ли использовать Thread Sanitizer для программ OpenMP?

...