2018-08-02 22:04:49 +03:00
|
|
|
|
<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>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<H1>Редукция в директиве parallel for </H1>
|
|
|
|
|
|
<p>Часто в цикле накапливается значение некоторой переменной, перед циклом эта
|
|
|
|
|
|
переменная инициализируется, а на каждой итерации к ней добавляется некоторое
|
|
|
|
|
|
значение или умножается на некоторое значение. Эта переменная должна быть
|
|
|
|
|
|
объявлена вне цикла, а значит, будет общей. В таком случае возможны ошибки при
|
|
|
|
|
|
параллельном выполнении:</p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<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>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>Два потока могут считать старое значение, затем первый поток прибавит единицу
|
|
|
|
|
|
и запишет в переменную a, затем второй поток прибавит единицу к старому значению
|
|
|
|
|
|
и запишет результат в переменную a. При этом изменения, сделанные первым
|
|
|
|
|
|
потоком, будут потеряны. Правильная работа программы возможна при некоторых
|
|
|
|
|
|
запусках, но возможны и ошибки.</p>
|
|
|
|
|
|
<p>Опция <code>reduction</code> позволяет обеспечить правильное накопление результата:</p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p><code><font color="#666666">{$omp parallel for reduction(действие : список переменных)}</font></code></p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
</blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>При этом все переменные из списка будут объявлены частными, таким образом,
|
|
|
|
|
|
разные потоки будут работать со своими экземплярами переменных. Эти экземпляры
|
|
|
|
|
|
будут инициализированы в зависимости от действия, а в конце цикла новое значение
|
|
|
|
|
|
переменной будет получено из значения этой переменной до цикла и всех частных
|
|
|
|
|
|
копий применением действия из опции.</p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<blockquote>
|
|
|
|
|
|
<p><code><b>var</b> a: integer := 1;<br>
|
|
|
|
|
|
<font color="#666666">{$omp parallel for reduction(+:a)}<br>
|
2025-11-11 22:04:03 +03:00
|
|
|
|
</font><b>for</b> <b>var</b> i:=1 <b>to</b> 2 <b>do</b><br>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
a := a+1;</code></p>
|
|
|
|
|
|
</blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>Здесь начальное значение переменной a – единица, для действия + локальные
|
|
|
|
|
|
копии будут инициализированы нулями, будет выполнено две итерации и у каждого
|
|
|
|
|
|
потока локальная копия переменной a примет значение 1. После завершения цикла к
|
|
|
|
|
|
начальному значению (1) будут прибавлены обе локальные копии, и результирующее
|
|
|
|
|
|
значение переменной a будет равно 3, так же как и при последовательном
|
|
|
|
|
|
выполнении. </p>
|
|
|
|
|
|
<p>В таблице приведены допустимые операторы редукции и значения, которыми
|
|
|
|
|
|
инициализируются локальные копии переменной редукции:</p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<p> </p>
|
|
|
|
|
|
<table border="1" width="100%" id="table2">
|
|
|
|
|
|
<tr>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<td>Оператор раздела reduction</td>
|
|
|
|
|
|
<td>Инициализированное значение</td>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td>+</td>
|
|
|
|
|
|
<td>0</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td>*</td>
|
|
|
|
|
|
<td>1</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td>-</td>
|
|
|
|
|
|
<td>0</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<td>and (побитовый)</td>
|
|
|
|
|
|
<td>~0 (каждый бит установлен)</td>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<td>or (побитовый)</td>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<td>0</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<td>xor (побитовый)</td>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<td>0</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<td>and (логический)</td>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<td>true</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<td>or (логический)</td>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<td>false</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
|
|
|
|
|
|
</html>
|