• B правой части каждого сообщения есть стрелки и . Не стесняйтесь оценивать ответы. Чтобы автору вопроса закрыть свой тикет, надо выбрать лучший ответ. Просто нажмите значок в правой части сообщения.

  • 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Дана последовательность натуральных чисел {a0…an–1}. Создать многопоточное приложение для вычисления

  • Автор темы jeckos
  • Дата начала
J

jeckos

Дана последовательность натуральных чисел {a0…an–1}. Создать многопоточное приложение для вычисления выражения a0-а1+a2-а3+a4-а5+...
 
  • Нравится
Реакции: -=S_U_N_Y=-
R

rrrFer

Сначала пишешь последовательный код:
Код:
double s = 0;
for (int i = 0; i < n; ++i) {
  if (i%2)
    s += a[i];
  else
    s -= a[i];
}
Что происходит? - перебираются последовательно элементы массива. Если индекс элемента четный - он добавляется к сумме, иначе - вычитается.

Теперь распараллеливаешь - например с OpenMP:
Код:
double s = 0;
#pragma omp parallel for reduction(+:s)
for (int i = 0; i < n; ++i) {
  if (i%2)
    s += a[i];
  else
    s -= a[i];
}

В чем вообще суть решения?
Тебе надо вычислить сумму, и очевидно, переменная в которой она хранится должна быть обще для потоков. Мы объявляем переменную s вне параллельной секции, поэтому она по умолчанию является общей (shared).

Мы могли бы в каждом потоке просто прибавлять элемент к сумме (как в последовательном решении), но это не сработает, ведь нельзя одновременно изменять одну и туже область памяти (она является разделяемым ресурсом). Тогда мы могли бы подумать, что проблему можно решить критической секцией (поместить в #pragma omp critical изменения общей переменной). Это будет работать, но очень медленно, ведь в критической секции в один момент времени может находиться только один поток, поэтому программа фактически превратится в последовательную (в ней будет много потоков, но они будут только то и делать, что ждать друг друга).

В этой связи, правильное решение - создать в каждом потоке свою локальную переменную, накопить в ней часть результата, а затем сложить все локальные переменные в общую. Складывать локальные переменные можно уже в критической секции - это оптимально.

Но вот эту самую операцию и выполняет опция reduction. Мы указываем reduction(+:s) - в результате, в каждом потоке создается своя локальная переменная s, тип которой берется из одноименной общей переменной. В качестве начального значения локальной переменной автоматически присваивается ноль, т.к. reduction выполняет оператор +. При выходе из параллельной области над всеми локальными переменными выполняется соотствующая операция и результат помещается в общую переменную.
 
  • Нравится
Реакции: Ishikawa, ApplePen и vital
V

vital

Очень хотелось бы, что бы тсу пригодился такой развернутый ответ.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!