Вы не инициализируете массивы threads_lo_bound
и threads_hi_bound
, поэтому они изначально содержат некоторые совершенно случайные значения (это источник случайности номер 1).
Затем вы входите в параллельную область, где необходимо понимать, что не все потоки будут перемещаться по коду синхронно, фактическая скорость каждого потока довольно случайна, так как он разделяет ЦП со многими другими программами,даже если они используют только 1%, это все равно будет отображаться (это источник случайности номер 2, я бы сказал, что это более важно для того, почему вы видите, что это работает время от времени).
Так что же происходит в случае сбоя кода?
Один из потоков (скорее всего, мастер) достигает критической области до того, как хотя бы один из потоков достигнетстрока, где вы устанавливаете threads_lo_bound[myid]
и threads_hi_bound[myid]
.
После этого, в зависимости от того, какими были эти случайные значения, хранящиеся в нем (вы обычно можете предполагать, что они выходили за пределы, ваш массив довольно мал, шансы того, что значения являются действительными индексами, довольно малы),Поток попытается украсть некоторые из заданий (которые не существуют), установив current_lower_bound
и / или current_upper_bound
на какое-то значение, которое находится вне диапазона ваших начальных массивов a, b, c
.
Затем он войдет во вторую итерацию вашего цикла while(affinity_steal != -1)
и получит доступ к памяти, которая выходит за границы, неизбежно приводящие к ошибке сегментации (в конечном счете, в принципе это неопределенное поведение, и сбой может произойти в любой момент посленеверный доступ к памяти или, в некоторых случаях, никогда, что приводит вас к убеждению, что все в порядке, когда это совершенно точно не так).
Исправление, конечно, простое, добавьте
#pragma omp barrier
непосредственно перед циклом while(affinity_steal != -1)
, чтобы убедиться, что все потоки достигли этой точки (т. е. синхронизировать потоки в этой точке), и границы правильно установлены, прежде чем вы перейдете в цикл.Затраты на это минимальны, но если по какой-то причине вы хотите избежать использования барьеров, вы можете просто установить значения массива перед входом в параллельную область.
Тем не менее, подобные ошибки, как правило, можно найти с помощью хорошего отладчика, я настоятельно рекомендую научиться их использовать, они значительно облегчают жизнь.