pascalabcnet/PABCNetHelp/LangGuide/OpenMP/reduction.html

103 lines
3.3 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>
&nbsp; 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>
&nbsp; a := a+1;</code></p>
</blockquote>
<p>Здесь начальное значение переменной a единица, для действия + локальные
копии будут инициализированы нулями, будет выполнено две итерации и у каждого
потока локальная копия переменной a примет значение 1. После завершения цикла к
начальному значению (1) будут прибавлены обе локальные копии, и результирующее
значение переменной a будет равно 3, так же как и при последовательном
выполнении. </p>
<p>В таблице приведены допустимые операторы редукции и значения, которыми
инициализируются локальные копии переменной редукции:</p>
<p>&nbsp;</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>