Маленькая программа OpenMP иногда замораживает (GCC, C, Linux)

StackOverflow https://stackoverflow.com/questions/4491063

  •  11-10-2019
  •  | 
  •  

Вопрос

Просто напишите небольшой тест OMP, и он не работает правильно все время:

#include <omp.h>
int main() {
  int i,j=0;
#pragma omp parallel
  for(i=0;i<1000;i++)
  {
#pragma omp barrier
    j+= j^i;
  }
  return j;
}

Использование j Для написания из всех потоков неверно в этом примере, но

  • Должно быть только ненутерминированная ценность j

  • У меня есть замораживание.

Скомпилируется с gcc-4.3.1 -fopenmp a.c -o gcc -static

Запустите на 4-ядерном сервере x86_core2 Linux: $ ./gcc и получил заморозку (иногда; как 1 замораживание за 4-5 быстрых пробежек).

Строка:

[pid 13118] futex(0x80d3014, FUTEX_WAKE, 1) = 1
[pid 13119] <... futex resumed> )       = 0
[pid 13118] futex(0x80d3020, FUTEX_WAIT, 251, NULL <unfinished ...>
[pid 13119] futex(0x80d3014, FUTEX_WAKE, 1) = 0
[pid 13119] futex(0x80d3020, FUTEX_WAIT, 251, NULL                       
                        <freeze>

Почему у меня замораживание (тупик)?

Это было полезно?

Решение

Попробуйте сделать меня приватным, чтобы у каждого цикла была собственная копия.

Теперь, когда у меня будет больше времени, я постараюсь объяснить. По умолчанию переменные в OpenMP используются. Есть несколько случаев, когда есть значения по умолчанию, которые делают переменные частными. Параллельные регионы не являются одним из них (поэтому ответ высокой производительности неверен). В вашей оригинальной программе у вас есть два условия гонки - один на I и один на J. Проблема в том, что на i. Каждый поток выполнит цикл некоторое количество раз, но, поскольку я изменяется каждым потоком, количество раз, когда любое поток выполняет цикл неопределенным. Поскольку все потоки должны выполнить барьер для удовлетворения барьера, вы придумаете случай, когда вы получите подвеску на барьер, который никогда не закончится, поскольку не все потоки выполнят его одинаково.

Поскольку спецификация OpenMP четко указывает (OMP Spec v3.0, раздел 2.8.3 Barrier Construct), что «последовательность регионов рабочих регионов и барьерных областей должна быть одинаковой для каждого потока в команде», ваша программа не совпадает и является и не совпадает и является и не совпадает. Таким образом, может иметь неопределенное поведение.

Другие советы

Вы пытаетесь добавить в одно и то же место из нескольких потоков. Вы не можете делать то, что пытаетесь сделать параллельно. Если вы хотите сделать сумму параллельно, вам нужно разделить ее на более мелкие кусочки и собрать их потом.

Обновление от A5B: правильная идея, но неправильная часть кода была обнаружена. А i Переменная изменяется обоими потоками.

@EJD, если я помечую меня как частную, будет ли моя программа соответствовать?

Извините - я только что видел этот вопрос. Технически, если вы отмечаете переменную «я» как частная, ваша программа будет совместимой с OpenMP. Тем не менее, на «J» все еще существует условие гонки, и, хотя ваша программа соответствует (поскольку существуют достоверные случаи, чтобы иметь условия гонки), значение «J» не определена (согласно спецификации OpenMP).

В одном из ваших предыдущих ответов вы сказали, что пытались измерить скорость реализации барьера. Есть несколько «тестов», которые вы, возможно, захотите посмотреть, что опубликовали результаты для различных конструкций OpenMP. Один из них был написан Марком Булл (EPCC, Университет Эдинбурга), другой (SPHINX), поступающий из Лоуренса Ливерморских Национальных Лабораторий (LLNL), а третий (Parkbench) происходит от японского компьютерного партнерства. Они могут предложить вам некоторое руководство.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top