![]() Проекты на Аде Уроки Ады Документация Конференции Разработки Примеры SSqrt asynch_transfer entry_family finalizer Каталог ПО Полезные ссылки Поиск в Сети Скачать Прочее |
Параллельные вычисленияПродемонстрируем параллельные вычисления в языке Ада на примере подсчета среднего квадратичного значения элементов массива. Задача: по данному массиву чисел A (1 .. N) найти среднее квадратичное, как S = Sqrt (A(1) ** 2 + A(2) ** 2 + ... + A(N) ** 2). Решение: будем выполнять подсчет суммы, используя несколько задач, работающих параллельно. Настраиваемая функция позволяет нам при необходимости легко поменять тип обрабатываемых значений. Функция принимает, как параметры, вектор исходных значений и желаемую степень распараллеливания. -- Sample of the parallel calculations in Ada. -- Distributed under the GNU General Public License -- Author: Dmitriy Anisimkov. generic type Number is digits <>; type Vector_Type is array (Positive range <>) of Number; function SSqrt (Vector : in Vector_Type; Tasks : in Positive) return Number; -- Vector is the numbers for calculation. -- Tasks is the number of parallel tasks for calculation. -- Number of tasks should not be more than number of processors for -- better performance. Реализация функции состоит из подпрограммы подсчета суммы Square_Sum и задачного типа Calculator, который вычисляет сумму квадратов пренадлежащего ему участка вектора. Жизненный цикл объекта типа Calculator состоит из получения диапазона участка, вычисления суммы квадратов и возврата результата.
-- Sample of the parallel calculations.
-- Distributed under the GNU General Public License
-- Author: Dmitriy Anisimkov.
with Ada.Numerics.Generic_Elementary_Functions;
function SSqrt
(Vector : in Vector_Type;
Tasks : in Positive) return Number
is
package GEL is new Ada.Numerics.Generic_Elementary_Functions (Number);
-- Generic instantiation for numeric functions.
function Square_Sum (First, Last : in Positive) return Number;
-- Calculates square sum from the First to the Last elements in the
-- vector.
task type Calculator is
entry Start (First, Last : in Positive);
-- First and Last is a subrange for this task square sum calculation.
entry Stop (Result : out Number);
-- Get the result after calculation.
end;
----------------
-- Calculator --
----------------
task body Calculator is
First, Last : Positive;
Sum : Number;
begin
accept Start (First, Last : Positive) do
-- Copy parameters to the local variables for be able start
-- calculation after rendezvous.
Calculator.First := First;
Calculator.Last := Last;
end Start;
-- Calculation.
Sum := Square_Sum (First, Last);
accept Stop (Result : out Number) do
-- Return result to the calling task.
Result := Sum;
end Stop;
end Calculator;
----------------
-- Square_Sum --
----------------
function Square_Sum (First, Last : in Positive) return Number is
Sum : Number := 0.0;
begin
for J in First .. Last loop
Sum := Sum + Vector (J) ** 2;
end loop;
return Sum;
end Square_Sum;
Sub_Length : constant Positive := Vector'Length / Tasks;
Calcs : array (1 .. Tasks - 1) of Calculator;
-- Tasks - 1 is to rest some elements for the calculation in the main task.
Index : Positive := Vector'First;
Next : Positive;
Sum : Number;
Subsum : Number;
begin
-- Dispatch subvectors to the parallel tasks.
for J in Calcs'Range loop
Next := Index + Sub_Length;
Calcs (J).Start (First => Index, Last => Next - 1);
Index := Next;
end loop;
-- Calculate square sum of the rest elements in the main task.
Sum := Square_Sum (Index, Vector'Last);
-- Get results from the parallel tasks.
for J in Calcs'Range loop
Calcs (J).Stop (Subsum);
Sum := Sum + Subsum;
end loop;
-- Calculate square root and return result.
return GEL.Sqrt (Sum);
end SSqrt;Главный модуль настраивает функцию на тип Long_Float и вычисляет среднее квадратичное двухсот элементов вектора, используя разную степень распараллеливания.
with Ada.Text_IO;
with SSqrt;
procedure SSqrt_Test is
subtype Number is Long_Float;
type Vector_Type is array (Positive range <>) of Number;
function Square_Sum_Sqrt is new SSqrt (Number, Vector_Type);
Sample : Vector_Type (1 .. 200);
Test_Sum : Number := 0.0;
begin
for J in Sample'Range loop
Sample (J) := Number (J);
Test_Sum := Test_Sum + Sample (J) ** 2;
end loop;
Ada.Text_IO.Put_Line
(Number'Image (Square_Sum_Sqrt (Sample, 1))
& Number'Image (Square_Sum_Sqrt (Sample, 2))
& Number'Image (Square_Sum_Sqrt (Sample, 3))
& ASCII.LF
& Number'Image (Square_Sum_Sqrt (Sample, 4) ** 2)
& Number'Image (Test_Sum));
end SSqrt_Test;Архив с тесктом этой программы доступен здесь. Эту программу любезно предоставил Дмитрий Анисимков.
|
|