Helgrind (Valgrind) и OpenMP (C): избежать ложных срабатываний?
Документация по инструменту обнаружения ошибок потока Valgrind Helgrind, найденная здесь
предупреждает, что если вы используете GCC для компиляции кода OpenMP, библиотека времени выполнения OpenMP GCC (libgomp.so) вызовет хаос ложных положительных отчетов о гонках данных из-за использования атомарных машинных инструкций и системных вызовов Linux futex вместо POSIX Pthreads примитивы. Он говорит вам, что вы можете решить эту проблему, перекомпилировав GCC с --disable-linux-futex
Вариант конфигурации.
Я попробовал это. Я скомпилировал и установил в локальный каталог (~ / GCC_Valgrind / gcc_install) новую версию GCC 4.7.0 (последний выпуск на момент написания этой статьи) с --disable-linux-futex
Вариант конфигурации. Затем я создал небольшую тестовую программу OpenMP (test1.c), в которой нет видимых гонок данных:
/* test1.c */
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 2
int a[NUM_THREADS];
int main(void) {
int i;
#pragma omp parallel num_threads(NUM_THREADS)
{
int tid = omp_get_thread_num();
a[tid] = tid + 1;
}
for (i = 0; i < NUM_THREADS; i++)
printf("%d ", a[i]);
printf("\n");
return EXIT_SUCCESS;
}
Я скомпилировал эту программу следующим образом
~/GCC_Valgrind/gcc_install/bin/gcc -Wall -fopenmp -static -L~/GCC_Valgrind/gcc_install/lib64 -L~/GCC_Valgrind/gcc_install/lib -o test1 test1.c
Тем не менее, я получил 30 ложных положительных отчетов о гонках данных! Все это происходит в коде libgomp. Затем я скомпилировал test1.c без -static
флаг, и снова запустил Хелгринд. На этот раз я получил только 9 ложных положительных отчетов о гонках данных, но это все еще слишком много - и без -static
флаг, я не могу отследить предполагаемую гонку в коде libgomp.
Кто-нибудь нашел способ уменьшить, если не устранить, количество ложных положительных отчетов о гонках данных от Helgrind, примененных к программе OpenMP, скомпилированной с GCC? Спасибо!
2 ответа
Извините, что добавил это как ответ, так как это больше комментарий, но он слишком длинный, чтобы его можно было использовать в качестве комментария, так что вот так:
С сайта, на который вы ссылаетесь.
Библиотека поддержки времени выполнения для GNU OpenMP (часть GCC), по крайней мере для версий GCC 4.2 и 4.3. Библиотека времени выполнения GNU OpenMP (libgomp.so) создает свои собственные примитивы синхронизации, используя комбинации атомарных инструкций памяти и системного вызова futex, что вызывает полный хаос, поскольку в Helgrind они не могут их "увидеть".
К счастью, это можно решить с помощью параметра времени конфигурации (для GCC). Перестройте GCC из исходного кода и настройте его с помощью --disable-linux-futex. Это заставляет libgomp.so использовать вместо этого стандартные потоковые примитивы POSIX. Обратите внимание, что это было протестировано с использованием GCC 4.2.3 и не было повторно протестировано с использованием более свежих версий GCC. Мы будем рады услышать о любых успехах или неудачах с более свежими версиями.
как вы упомянули в своем посте, это связано с libgomp.so
, но это общий объект, поэтому я не вижу, как вы можете передать флаг -static и все еще использовать эту библиотеку. Я просто дезинформирован?
Также обратите внимание, что если omp_set_lock
используется в коде omp.h
путь должен быть заменен из-за другого размера структуры блокировки. См. https://xrunhprof.wordpress.com/2018/08/27/tsan-with-openmp/
Шаги, которые заставят это работать:
- Перекомпилируйте gcc (включая libgomp), используя
--disable-linux-futex
- Убедитесь, что вы используете futex free gcc при компиляции вашей программы.
- Убедитесь, что при загрузке вашей программы система загрузит бесплатную библиотеку futex (библиотека обычно находится в
GCC-OBJ-DIR/PLATFORM/libgomp/.libs
). Например, установивLD_LIBRARY_PATH
переменная окружения:
export LD_LIBRARY_PATH = ~ / gcc-4.8.1-nofutex / x86_64-unknown-linux-gnu / libgomp /.libs: