/
n-dimens
/
pascalabcnet
Обзор
Документация
Войти
/
n-dimens
/
pascalabcnet
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
PABCNetHelp/LangGuide/OpenMP/parallelfor.html
145 строк
8 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"> <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> <H1><span lang="ru">Директива </span>parallel for</H1> <p>Директива <code>parallel for</code> обеспечивает распараллеливание следующего за ней цикла.</p> <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> тело цикла</code></p> </blockquote> <p>Здесь будет создано несколько потоков и разные итерации цикла будут распределены по этим потокам. Количество потоков, как правило, совпадает с количеством ядер процессора, но в некоторых случаях могут быть отличия, например, если поток ожидает ввод данных от пользователя, могут создаваться дополнительные потоки, чтобы по возможности задействовать все доступные ядра.</p> <p>Все переменные, описанные вне параллельного цикла, будут разделяемыми, то есть, если в теле цикла есть обращение к таким переменным, все потоки будут обращаться к одной и той же ячейке памяти. Все переменные, объявленные внутри цикла, будут частными, то есть у каждого потока будет своя копия этой переменной.</p> <p>Опция <code>private</code> позволяет переменные, описанные вне цикла, сделать частными. Опция записывается так:</p> <blockquote> <p><code><font color="#666666">{$omp parallel for private(список переменных)}</font></code></p> </blockquote> <p>Список переменных – одна или несколько переменных через запятую.</p> <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> <p>В этом случае переменные a и b будут частными, и присваивание этим переменным в одном потоке не будет влиять на другие потоки.</p> <p>Ограничение: счетчики распараллеливаемого цикла и вложенных циклов должны быть объявлены в заголовке цикла.</p> <p>Не все циклы можно распараллеливать. Если на разных итерациях происходит обращение к одной и той же переменной и при этом ее значение меняется – распараллеливание такого цикла приведет к ошибкам, при разных запусках могут получаться разные результаты в зависимости от того, в каком порядке происходили обращения к этой переменной.</p> <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> <p>Здесь на первой итерации происходит чтение второго элемента массива, а на второй итерации – запись этого же элемента. Если первая итерация выполнится раньше второй – в первый элемент массива запишется значение из второго, а если позже – то из третьего элемента массива.</p> <blockquote> <p><code><b>var</b> a:integer;<br> <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> ... := a; //к этому моменту a может быть изменено другим потоком<br> <b>end</b>;</code></p> </blockquote> <p>Значение переменной a после этого цикла может быть любым в диапазоне от 1 до 10.</p> <p>Наиболее эффективно распараллеливаются циклы, каждая итерация которых выполняется достаточно долго. Если тело цикла состоит из небольшого количества простых операторов, затраты на создание потоков и распределение нагрузки между ними могут превысить выигрыш от параллельного выполнения цикла.</p> <p><b>Пример<span lang="ru"> параллельного перемножения матриц</span></b></p> <p><span lang="ru">Перемножение матриц - классический пример иллюстрации параллельности. Вычисление различных элементов матрицы происходит независимо, поэтому не надо предусматривать никаких средств синхронизации.</span></p> <blockquote> <p><code><b>uses</b> Arrays;<br> <br> <b>procedure</b> ParallelMult(a,b,c: <b>array</b> [,] <b>of</b> real; n: 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 := Arrays.CreateRandomRealMatrix(n,n);<br> <b><span lang="ru"> </span>var</b> b := Arrays.CreateRandomRealMatrix(n,n);<br> <b><span lang="ru"> </span>var</b> c := new real[n,n];<br> <span lang="ru"> </span>ParallelMult(a,b,c,n);<br> <span lang="ru"> </span>writeln('Параллельное перемножение матриц: ',Milliseconds,' миллисекунд');<br> <b><span lang="ru"> </span>var</b> d := Milliseconds;<br> <span lang="ru"> </span>Mult(a,b,c,n);<br> <span lang="ru"> </span>writeln('Непараллельное перемножение матриц: ',Milliseconds-d,' миллисекунд');<br> <b>end</b>.</code></p> </blockquote> </body> </html>