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">
|
|
|
|
|
|
<param name="Keyword" value="private">
|
|
|
|
|
|
</object>
|
|
|
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
|
|
|
|
|
|
<title></title>
|
|
|
|
|
|
<link rel="StyleSheet" href="../../default.css">
|
|
|
|
|
|
<style>
|
|
|
|
|
|
<!--
|
|
|
|
|
|
span.a
|
|
|
|
|
|
{color:#4F81BD;
|
|
|
|
|
|
font-weight:bold;
|
|
|
|
|
|
font-style:italic}
|
|
|
|
|
|
-->
|
|
|
|
|
|
</style>
|
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
|
|
<body>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<H1><span lang="ru">Директива </span>parallel for</H1>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
|
|
|
|
|
|
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>Директива <code>parallel for</code> обеспечивает распараллеливание следующего
|
|
|
|
|
|
за ней цикла.</p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<blockquote>
|
|
|
|
|
|
<p><code><font color="#666666">{$omp parallel for}<br>
|
|
|
|
|
|
</font>
|
|
|
|
|
|
<b>for</b> <b>var</b> i: integer:=1 <b>to</b><b> </b>10 <b>do</b><br>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
тело цикла</code></p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
</blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>Здесь будет создано несколько потоков и разные итерации цикла будут
|
|
|
|
|
|
распределены по этим потокам. Количество потоков, как правило, совпадает с
|
|
|
|
|
|
количеством ядер процессора, но в некоторых случаях могут быть отличия,
|
|
|
|
|
|
например, если поток ожидает ввод данных от пользователя, могут создаваться
|
|
|
|
|
|
дополнительные потоки, чтобы по возможности задействовать все доступные ядра.</p>
|
|
|
|
|
|
<p>Все переменные, описанные вне параллельного цикла, будут разделяемыми, то
|
|
|
|
|
|
есть, если в теле цикла есть обращение к таким переменным, все потоки будут
|
|
|
|
|
|
обращаться к одной и той же ячейке памяти. Все переменные, объявленные внутри
|
|
|
|
|
|
цикла, будут частными, то есть у каждого потока будет своя копия этой
|
|
|
|
|
|
переменной.</p>
|
|
|
|
|
|
<p>Опция <code>private</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 private(список переменных)}</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,b: integer;<br>
|
|
|
|
|
|
<font color="#666666">{$omp parallel for private(a, b)}<br>
|
|
|
|
|
|
</font>
|
|
|
|
|
|
<b>for</b> <b>var</b> i: integer:=1 <b>to</b> 10 <b>do</b><br>
|
|
|
|
|
|
a := ...</code></p>
|
|
|
|
|
|
</blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>В этом случае переменные a и b будут частными, и присваивание этим переменным
|
|
|
|
|
|
в одном потоке не будет влиять на другие потоки.</p>
|
|
|
|
|
|
<p>Ограничение: счетчики распараллеливаемого цикла и вложенных циклов должны
|
|
|
|
|
|
быть объявлены в заголовке цикла.</p>
|
|
|
|
|
|
<p>Не все циклы можно распараллеливать. Если на разных итерациях происходит
|
|
|
|
|
|
обращение к одной и той же переменной и при этом ее значение меняется –
|
|
|
|
|
|
распараллеливание такого цикла приведет к ошибкам, при разных запусках могут
|
|
|
|
|
|
получаться разные результаты в зависимости от того, в каком порядке происходили
|
|
|
|
|
|
обращения к этой переменной.</p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<blockquote>
|
|
|
|
|
|
<p><code><font color="#666666">{$omp parallel for}<br>
|
|
|
|
|
|
</font>
|
|
|
|
|
|
<b>for</b> <b>var</b> i:=1 <b>to</b> 2 <b>do</b><br>
|
|
|
|
|
|
a[i] := a[i+1];</code></p>
|
|
|
|
|
|
</blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>Здесь на первой итерации происходит чтение второго элемента массива, а на
|
|
|
|
|
|
второй итерации – запись этого же элемента. Если первая итерация выполнится
|
|
|
|
|
|
раньше второй – в первый элемент массива запишется значение из второго, а если
|
|
|
|
|
|
позже – то из третьего элемента массива.</p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<blockquote>
|
2025-11-11 22:04:03 +03:00
|
|
|
|
<p><code><b>var</b> a: integer;<br>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<font color="#666666">{$omp parallel for}<br>
|
|
|
|
|
|
</font>
|
|
|
|
|
|
<b>for</b> <b>var</b> i:=1 <b>to</b> 10 <b>do</b><br>
|
|
|
|
|
|
<b>begin</b><br>
|
|
|
|
|
|
a := i;<br>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
... := a; //к этому моменту a может быть изменено другим потоком<br>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<b>end</b>;</code></p>
|
|
|
|
|
|
</blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>Значение переменной a после этого цикла может быть любым в диапазоне от 1 до
|
2018-08-02 22:04:49 +03:00
|
|
|
|
10.</p>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>Наиболее эффективно распараллеливаются циклы, каждая итерация которых
|
|
|
|
|
|
выполняется достаточно долго. Если тело цикла состоит из небольшого количества
|
|
|
|
|
|
простых операторов, затраты на создание потоков и распределение нагрузки между
|
|
|
|
|
|
ними могут превысить выигрыш от параллельного выполнения цикла.</p>
|
|
|
|
|
|
<p><b>Пример<span lang="ru"> параллельного перемножения матриц</span></b></p>
|
|
|
|
|
|
<p><span lang="ru">Перемножение матриц - классический пример иллюстрации
|
|
|
|
|
|
параллельности. Вычисление различных элементов матрицы происходит независимо,
|
|
|
|
|
|
поэтому не надо предусматривать никаких средств синхронизации.</span></p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<blockquote>
|
2025-11-11 22:04:03 +03:00
|
|
|
|
<p><code><b>procedure</b> ParallelMult(a,b,c: <b>array</b> [,] <b>of</b> real; n:
|
2018-08-02 22:04:49 +03:00
|
|
|
|
integer);<br>
|
|
|
|
|
|
<b>begin</b><br>
|
|
|
|
|
|
<font color="#666666"><span lang="ru"> </span>{$omp parallel for }<br>
|
|
|
|
|
|
</font><span lang="ru"> </span><b>for</b> <b>var</b> i:=0 <b>to</b>
|
|
|
|
|
|
n-1 <b>do</b><br>
|
|
|
|
|
|
<span lang="ru"> </span><b>for</b> <b>var</b> j:=0 <b>to</b> n-1 <b>do</b><br>
|
|
|
|
|
|
<span lang="ru"> </span><b>begin</b> <br>
|
|
|
|
|
|
<span lang="ru"> </span>c[i,j]:=0;<br>
|
|
|
|
|
|
<span lang="ru"> </span><b>for</b> <b>var</b> l:=0 <b>to</b>
|
|
|
|
|
|
n-1 <b>do</b><br>
|
|
|
|
|
|
<span lang="ru"> </span>c[i,j]:=c[i,j]+a[i,l]*b[l,j];<br>
|
|
|
|
|
|
<span lang="ru"> </span><b>end</b>;<br>
|
|
|
|
|
|
<b>end</b>;<br>
|
|
|
|
|
|
<br>
|
|
|
|
|
|
<b>procedure</b> Mult(a,b,c: <b>array</b> [,] <b>of</b> real; n: integer);<br>
|
|
|
|
|
|
<b>begin</b><br>
|
|
|
|
|
|
<span lang="ru"> </span><b>for</b> <b>var</b> i:=0 <b>to</b>
|
|
|
|
|
|
n-1 <b>do</b><br>
|
|
|
|
|
|
<span lang="ru"> </span><b>for</b> <b>var</b> j:=0 <b>to</b> n-1 <b>do</b><br>
|
|
|
|
|
|
<span lang="ru"> </span><b>begin</b> <br>
|
|
|
|
|
|
<span lang="ru"> </span>c[i,j]:=0;<br>
|
|
|
|
|
|
<span lang="ru"> </span><b>for</b> <b>var</b> l:=0 <b>to</b>
|
|
|
|
|
|
n-1 <b>do</b><br>
|
|
|
|
|
|
<span lang="ru"> </span>c[i,j]:=c[i,j]+a[i,l]*b[l,j];<br>
|
|
|
|
|
|
<span lang="ru"> </span><b>end</b>;<br>
|
|
|
|
|
|
<b>end</b>;<br>
|
|
|
|
|
|
<br>
|
|
|
|
|
|
<b>const</b> n = 400;<br>
|
|
|
|
|
|
<br>
|
|
|
|
|
|
<b>begin</b><br>
|
|
|
|
|
|
<b><span lang="ru"> </span>var</b> a :=
|
2025-11-11 22:04:03 +03:00
|
|
|
|
MatrRandomReal(n,n);<br>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<b><span lang="ru"> </span>var</b> b :=
|
2025-11-11 22:04:03 +03:00
|
|
|
|
MatrRandomReal(n,n);<br>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<b><span lang="ru"> </span>var</b> c := new real[n,n];<br>
|
|
|
|
|
|
<span lang="ru"> </span>ParallelMult(a,b,c,n);<br>
|
2025-11-11 22:04:03 +03:00
|
|
|
|
<span lang="ru"> </span>Println('Параллельное перемножение матриц:',Milliseconds,'миллисекунд');<br>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<b><span lang="ru"> </span>var</b> d := Milliseconds;<br>
|
|
|
|
|
|
<span lang="ru"> </span>Mult(a,b,c,n);<br>
|
2025-11-11 22:04:03 +03:00
|
|
|
|
<span lang="ru"> </span>Println('Непараллельное перемножение матриц:',Milliseconds-d,'миллисекунд');<br>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<b>end</b>.</code></p>
|
|
|
|
|
|
</blockquote>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
|
|
|
|
|
|
</html>
|