В некоторых отношениях это похоже на домашнее задание, которое я ненавижу делать для людей. С другой стороны, приведенные выше ответы не совсем точны, и я считаю, что их следует исправить.
Во-первых, хотя в этом примере и общие, и частные предложения не нужны, я не согласен с Конрадом, что их не следует использовать. Одна из наиболее распространенных проблем, связанных с распараллеливанием кода людьми, заключается в том, что они не тратят время на то, чтобы понять, как используются переменные. Неприватизация и / или защита общих переменных, которые должны быть, составляют наибольшее количество проблем, которые я вижу. Выполнение упражнения по изучению того, как используются переменные, и помещение их в соответствующие разделенные, частные и т. Д. Предложения значительно уменьшат количество проблем, с которыми вы столкнулись.
Что касается вопроса о барьерах, то в первом цикле может быть предложение nowait, поскольку во втором цикле значение, вычисленное (a), не используется. Второй цикл может иметь предложение nowait, только если вычисленное значение (c) не используется до вычисления значений (т.е. нет зависимости). В исходном коде примера во втором цикле есть nowait, но явный барьер перед третьим циклом. Это нормально, поскольку ваш профессор пытался показать использование явного барьера - хотя отключение nowait во втором цикле сделает избыточным явный барьер (так как в конце цикла есть неявный барьер).
С другой стороны, nowait во втором цикле и явный барьер могут вообще не понадобиться. До спецификации OpenMP V3.0 многие полагали, что что-то было правдой, что не было разъяснено в спецификации. Со спецификацией OpenMP V3.0 в раздел 2.5.1 Loop Construct было добавлено следующее, таблица 2-1, предложение расписания вид значения, статическое (расписание):
Соответствующая реализация статического расписания должна обеспечивать
назначение номеров логических итераций потокам будет использоваться в два цикла
области, если выполняются следующие условия: 1) обе области цикла имеют
одинаковое количество итераций цикла, 2) обе области цикла имеют одинаковое значение
указан chunk_size, или в обеих областях цикла не указано значение chunk_size, и 3)
Обе области петли связаны с одной и той же параллельной областью. Зависимость данных между
одинаковые логические итерации в двух таких циклах гарантированно будут выполнены
разрешить безопасное использование предложения nowait (см. раздел A.9 на стр. 170 для
примеры).
Теперь в вашем примере расписание не было показано ни в одном из циклов, так что это может или не может выполняться. Причина в том, что расписание по умолчанию определяется реализацией, и хотя большинство реализаций в настоящее время определяют расписание по умолчанию как статическое, это не гарантируется. Если ваш профессор установил статический тип расписания без chunk-size во всех трех циклах, то nowait можно было бы использовать в первом и втором циклах, и никакой барьер (ни явный, ни явный) не понадобился бы между второй и третьей петлями вообще.
Теперь перейдем к третьему циклу и вашему вопросу о текущем состоянии и сокращении. Как указал Мичи, спецификация OpenMP позволяет указывать и то, и другое (сокращение и nowait). Однако неверно, что для завершения сокращения синхронизации не требуется. В этом примере неявный барьер (в конце третьего цикла) может быть удален с помощью nowait. Это связано с тем, что сокращение (сумма) не используется до того, как будет обнаружен неявный барьер параллельной области.
Если вы посмотрите на спецификацию OpenMP V3.0, раздел 2.9.3.6 сокращения, вы найдете следующее:
Если nowait не используется, вычисление сокращения будет завершено в конце
строить; однако, если предложение сокращения используется в конструкции, которой сейчас являетсятакже применяется, доступ к исходному элементу списка создаст расу и, таким образом,
неуказанный эффект, если синхронизация не гарантирует, что они происходят после того, как все потоки имеют
выполнил все их итерации или конструкции сечения, и вычисление редукции
завершил и сохранил вычисленное значение этого элемента списка. Проще всего это может быть
обеспечивается через барьерную синхронизацию.
Это означает, что если вы хотите использовать переменную суммы в параллельной области после третьего цикла, то вам потребуется барьер (неявный или явный), прежде чем использовать его. Поскольку пример стоит сейчас, это правильно.