/
n-dimens
/
pascalabcnet
Обзор
Документация
Войти
/
n-dimens
/
pascalabcnet
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
PABCNetHelp/LangGuide/OpenMP/reduction.html
103 строки
5 KB
samuraiGH
adding working-tree-encoding attribute (#3325)
07 ноя 2025, 16:12
Не верифицирован
07 ноя 2025, 16:12
cf1fd29
Код
Авторство
О чём код?
<html> <head> <object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e"> <param name="Keyword" value="parallel"> </object> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <title></title> <link rel="StyleSheet" href="../../default.css"> <style> <!-- table.MsoNormalTable {mso-style-parent:""; font-size:10.0pt; font-family:"Times New Roman"; } --> </style> </head> <body> <H1>Редукция в директиве parallel for </H1> <p>Часто в цикле накапливается значение некоторой переменной, перед циклом эта переменная инициализируется, а на каждой итерации к ней добавляется некоторое значение или умножается на некоторое значение. Эта переменная должна быть объявлена вне цикла, а значит, будет общей. В таком случае возможны ошибки при параллельном выполнении:</p> <blockquote> <p><code><b>var</b> a: integer:=0;<br> <font color="#666666">{$omp parallel for}<br> </font><b>for</b> <b>var</b> i:integer:=1 <b>to</b> 100 <b>do</b><br> a := a+1;</code></p> </blockquote> <p>Два потока могут считать старое значение, затем первый поток прибавит единицу и запишет в переменную a, затем второй поток прибавит единицу к старому значению и запишет результат в переменную a. При этом изменения, сделанные первым потоком, будут потеряны. Правильная работа программы возможна при некоторых запусках, но возможны и ошибки.</p> <p>Опция <code>reduction</code> позволяет обеспечить правильное накопление результата:</p> <blockquote> <p><code><font color="#666666">{$omp parallel for reduction(действие : список переменных)}</font></code></p> </blockquote> <p>При этом все переменные из списка будут объявлены частными, таким образом, разные потоки будут работать со своими экземплярами переменных. Эти экземпляры будут инициализированы в зависимости от действия, а в конце цикла новое значение переменной будет получено из значения этой переменной до цикла и всех частных копий применением действия из опции.</p> <blockquote> <p><code><b>var</b> a: integer := 1;<br> <font color="#666666">{$omp parallel for reduction(+:a)}<br> </font><b>for</b> <b>var</b> i: integer:=1 <b>to</b> 2 <b>do</b><br> a := a+1;</code></p> </blockquote> <p>Здесь начальное значение переменной a – единица, для действия + локальные копии будут инициализированы нулями, будет выполнено две итерации и у каждого потока локальная копия переменной a примет значение 1. После завершения цикла к начальному значению (1) будут прибавлены обе локальные копии, и результирующее значение переменной a будет равно 3, так же как и при последовательном выполнении. </p> <p>В таблице приведены допустимые операторы редукции и значения, которыми инициализируются локальные копии переменной редукции:</p> <p> </p> <table border="1" width="100%" id="table2"> <tr> <td>Оператор раздела reduction</td> <td>Инициализированное значение</td> </tr> <tr> <td>+</td> <td>0</td> </tr> <tr> <td>*</td> <td>1</td> </tr> <tr> <td>-</td> <td>0</td> </tr> <tr> <td>and (побитовый)</td> <td>~0 (каждый бит установлен)</td> </tr> <tr> <td>or (побитовый)</td> <td>0</td> </tr> <tr> <td>xor (побитовый)</td> <td>0</td> </tr> <tr> <td>and (логический)</td> <td>true</td> </tr> <tr> <td>or (логический)</td> <td>false</td> </tr> </table> </body> </html>