W Cat - Описание языка PascalABC.NET
- Название:Описание языка PascalABC.NET
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
W Cat - Описание языка PascalABC.NET краткое содержание
PascalABC.NET — это язык программирования Паскаль нового поколения, включающий классический Паскаль, большинство возможностей языка Delphi, а также ряд собственных расширений. Он реализован на платформе Microsoft.NET и содержит все современные языковые средства: классы, перегрузку операций, интерфейсы, обработку исключений, обобщенные классы и подпрограммы, сборку мусора, лямбда-выражения, средства параллельного программирования.
PascalABC.NET является мультипарадигменным языком: на нем можно программировать в структурном, объектно-ориентированном и функциональном стилях.
PascalABC.NET — это также простая и мощная интегрированная среда разработки, поддерживающая технологию IntelliSense, содержащая средства автоформатирования, встроенный отладчик и встроенный дизайнер форм.
Описание языка PascalABC.NET - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
{$omp parallel for}
for vari:=1 to2 do
a[i] := a[i+1];
Здесь на первой итерации происходит чтение второго элемента массива, а на второй итерации – запись этого же элемента. Если первая итерация выполнится раньше второй – в первый элемент массива запишется значение из второго, а если позже – то из третьего элемента массива.
vara:integer;
{$omp parallel for}
for vari:=1 to10 do
begin
a := i;
... := a; //к этому моменту a может быть изменено другим потоком
end;
Значение переменной a после этого цикла может быть любым в диапазоне от 1 до 10.
Наиболее эффективно распараллеливаются циклы, каждая итерация которых выполняется достаточно долго. Если тело цикла состоит из небольшого количества простых операторов, затраты на создание потоков и распределение нагрузки между ними могут превысить выигрыш от параллельного выполнения цикла.
Пример параллельного перемножения матриц
Перемножение матриц - классический пример иллюстрации параллельности. Вычисление различных элементов матрицы происходит независимо, поэтому не надо предусматривать никаких средств синхронизации.
usesArrays;
procedureParallelMult(a,b,c: array[,] ofreal; n: integer);
begin
{$omp parallel for }
for vari:=0 ton-1 do
for varj:=0 ton-1 do
begin
c[i,j]:=0;
for varl:=0 ton-1 do
c[i,j]:=c[i,j]+a[i,l]*b[l,j];
end;
end;
procedureMult(a,b,c: array[,] ofreal; n: integer);
begin
{$omp parallel for }
for vari:=0 ton-1 do
for varj:=0 ton-1 do
begin
c[i,j]:=0;
for varl:=0 ton-1 do
c[i,j]:=c[i,j]+a[i,l]*b[l,j];
end;
end;
constn = 400;
begin
vara := Arrays.CreateRandomRealMatrix(n,n);
varb := Arrays.CreateRandomRealMatrix(n,n);
varc := new real[n,n];
ParallelMult(a,b,c,n);
writeln('Параллельное перемножение матриц: ',Milliseconds,' миллисекунд');
vard := Milliseconds;
Mult(a,b,c,n);
writeln('Непараллельное перемножение матриц: ',Milliseconds-d,' миллисекунд');
end.
Редукция в директиве parallel for
Часто в цикле накапливается значение некоторой переменной, перед циклом эта переменная инициализируется, а на каждой итерации к ней добавляется некоторое значение или умножается на некоторое значение. Эта переменная должна быть объявлена вне цикла, а значит, будет общей. В таком случае возможны ошибки при параллельном выполнении:
vara: integer:=0;
{$omp parallel for}
for vari:integer:=1 to100 do
a := a+1;
Два потока могут считать старое значение, затем первый поток прибавит единицу и запишет в переменную a, затем второй поток прибавит единицу к старому значению и запишет результат в переменную a. При этом изменения, сделанные первым потоком, будут потеряны. Правильная работа программы возможна при некоторых запусках, но возможны и ошибки.
Опция reduction позволяет обеспечить правильное накопление результата:
{$omp parallel for reduction(действие : список переменных)}
При этом все переменные из списка будут объявлены частными, таким образом, разные потоки будут работать со своими экземплярами переменных. Эти экземпляры будут инициализированы в зависимости от действия, а в конце цикла новое значение переменной будет получено из значения этой переменной до цикла и всех частных копий применением действия из опции.
vara: integer := 1;
{$omp parallel for reduction(+:a)}
for vari: integer:=1 to2 do
a := a+1;
Здесь начальное значение переменной a – единица, для действия + локальные копии будут инициализированы нулями, будет выполнено две итерации и у каждого потока локальная копия переменной a примет значение 1. После завершения цикла к начальному значению (1) будут прибавлены обе локальные копии, и результирующее значение переменной a будет равно 3, так же как и при последовательном выполнении.
В таблице приведены допустимые операторы редукции и значения, которыми инициализируются локальные копии переменной редукции:
Оператор раздела reduction |
Инициализированное значение |
+ |
0 |
* |
1 |
- |
0 |
and (побитовый) |
~0 (каждый бит установлен) |
or (побитовый) |
0 |
xor (побитовый) |
0 |
and (логический) |
true |
or (логический) |
false |
Параллельные секции и директива parallel sections
Директива parallel sections обеспечивает параллельное выполнение нескольких операторов, простых или составных.
{$omp parallel sections}
begin
секция 1;
секция 2;
...;
end;
Каждый оператор в блоке begin... end, следующем за директивой является отдельной секцией.
{$omp parallel sections}
begin
оператор 1;
оператор 2;
begin
оператор 3;
оператор 4;
оператор 5;
end;
end;
Здесь описаны три параллельные секции, первая – оператор 1, вторая – оператор 2 и третья – блок begin ... end, состоящий из операторов 3-5.
Все переменные, описанные вне параллельных секций, будут разделяемыми, то есть, если в секциях есть обращение к таким переменным, то потоки, выполняющие эти секции, будут обращаться к одной и той же ячейке памяти. Все переменные, объявленные внутри секции, будут доступны только в той секции, в которой они объявлены.
Корректная работа параллельных секций возможна, только если секции независимы друг от друга – если они могут выполняться в любом порядке, не обращаются к одним и тем же переменным и не изменяют их.
Синхронизация и директива critical
Директива critical исключает параллельное выполнение следующего за ней оператора.
{$omp critical имя}
оператор ;
Этот оператор образует критическую секцию – участок кода, который не может выполняться одновременно несколькими потоками.
Только критические секции с одинаковыми именами не могут выполняться одновременно. Если один поток уже выполняет критическую секцию, а второй пытается войти в секцию с таким же именем, он будет заблокирован до тех пор, пока первый поток не выйдет за пределы критической секции.
Критические секции можно использовать при обращении к общим переменным, чтобы избежать потерь данных.
vara:integer:=0;
{$omp parallel for}
for vari:integer:=1 to100 do
{$omp critical}
a:=a+1;
Здесь критическую секцию можно использовать вместо редукции. Весь оператор a:=a+1 выполнится одним потоком и только потом – другим. Однако использование критических секций обычно снижает эффективность за счет последовательного выполнения этих участков. В этом примере все тело цикла является критической секцией, поэтому весь цикл будет выполнен последовательно.
Читать дальшеИнтервал:
Закладка: