Ada 是否有必要将共享阵列数据包装为受保护的类型?

Ada 是否有必要将共享阵列数据包装为受保护的类型?,ada,Ada,我知道这通常是不好的做法(ARM可能会说这是未定义的行为),但是我正在尝试编写一个包含许多浮点数的快速文本解析器,如果将加载的文本包装成受保护的类型将非常昂贵,因为数据是逐字符检查的,并且可能有多达一百万个浮点数或在堆栈上传递一个切片 在Ada(GNAT)中,如果数组从不写入而只读取,是否可以“安全”地将未受保护的数组与多个任务分开使用? 例如: Text : array (1..1_000_000) of Character := ... begin Task_1.Initializ

我知道这通常是不好的做法(ARM可能会说这是未定义的行为),但是我正在尝试编写一个包含许多浮点数的快速文本解析器,如果将加载的文本包装成受保护的类型将非常昂贵,因为数据是逐字符检查的,并且可能有多达一百万个浮点数或在堆栈上传递一个切片

在Ada(GNAT)中,如果数组从不写入而只读取,是否可以“安全”地将未受保护的数组与多个任务分开使用?

例如:

 Text : array (1..1_000_000) of Character := ...
 begin
   Task_1.Initialize (Start_Index => 1, End_Index => 10_000);
   Task_2.Initialize (Start_Index => 10_001, End_Index => 20_000);
 ...

对。这是安全的,因为不存在与读取数据相关的争用条件,也不存在临时重叠的写入操作。 例如,下面的代码使用这种技术对整数数组执行并行加法

package Parallel_Addition is
   type Data_Array is array(Integer range <>) of Integer;
   type Data_Access is access all Data_Array;
   function Sum(Item : in not null Data_Access) return Integer;
end Parallel_Addition;

package body Parallel_Addition is

   ---------
   -- Sum --
   ---------

   function Sum (Item : in not null Data_Access) return Integer is
      task type Adder is
         entry Set (Min : Integer; Max : Integer);
         entry Report (Value : out Integer);
      end Adder;

      task body Adder is
         Total : Integer := 0;
         First : Integer;
         Last  : Integer;
      begin
         accept Set (Min : Integer; Max : Integer) do
            First := Min;
            Last  := Max;
         end Set;
         for I in First .. Last loop
            Total := Total + Item (I);
         end loop;
         accept Report (Value : out Integer) do
            Value := Total;
         end Report;
      end Adder;
      A1  : Adder;
      A2  : Adder;
      R1  : Integer;
      R2  : Integer;
      Mid : constant Integer := (Item'Length / 2) + Item'First;
   begin
      A1.Set (Min => Item'First, Max => Mid);
      A2.Set (Min => Mid + 1, Max => Item'Last);
      A1.Report (R1);
      A2.Report (R2);
      return R1 + R2;
   end Sum;

end Parallel_Addition;

with Parallel_Addition; use Parallel_Addition;
with Ada.Text_IO;       use Ada.Text_IO;
with Ada.Calendar;      use Ada.Calendar;

procedure Parallel_Addition_Test is
   The_Data : Data_Access := new Data_Array (1 .. Integer'Last / 5);
   Start    : Time;
   Stop     : Time;
   The_Sum  : Integer;

begin
   The_Data.all := (others => 1);
   Start        := Clock;
   The_Sum      := Sum (The_Data);
   Stop         := Clock;
   Put_Line ("The sum is: " & Integer'Image (The_Sum));
   Put_Line
     ("Addition elapsed time is " &
      Duration'Image (Stop - Start) &
        " seconds.");
   Put_Line
     ("Time per addition operation is " &
        Float'Image(Float(Stop - Start) / Float(The_Data'Length)) &
        " seconds.");
end Parallel_Addition_Test;
package并行添加
类型数据_数组是整数的数组(整数范围);
类型Data\u Access为Access all Data\u数组;
函数和(项:在非空数据访问中)返回整数;
端部平行加成;
包体平行添加为
---------
--总数--
---------
函数和(项:在非空数据访问中)返回整数为
任务型加法器
条目集(最小值:整数;最大值:整数);
输入报告(值:out Integer);
末端加法器;
任务体加法器是
合计:整数:=0;
第一:整数;
最后:整数;
开始
接受集(最小值:整数;最大值:整数)do
第一:=Min;
最后:=最大值;
端集;
因为我是第一个。。最后一圈
总计:=总计+项目(I);
端环;
接受报告(值:out Integer)do
值:=总计;
结束报告;
末端加法器;
A1:加法器;
A2:加法器;
R1:整数;
R2:整数;
Mid:常量整数:=(项长度/2)+项首;
开始
A1.设置(最小值=>第一项,最大值=>中间值);
A2.设置(最小=>Mid+1,最大=>Item'Last);
A1.报告(R1);
A2.报告(R2);
返回R1+R2;
最终金额;
端部平行加成;
并行_加法;采用平行加法;
使用Ada.Text_IO;使用Ada.Text\u IO;
日历;使用Ada.Calendar;
程序并行加法测试
_数据:数据访问:=新数据数组(1..Integer'Last/5);
开始:时间;
停止:时间;
_和:整数;
开始
_Data.all:=(其他=>1);
开始:=时钟;
_总和:=总和(_数据);
停止:=时钟;
Put_行(“总和是:“&Integer”图像(总和));
放线
(“添加经过的时间为”&
持续时间图像(停止-启动)&
“秒。”);
放线
(“每次添加操作的时间为”&
浮动图像(浮动(停止-启动)/浮动(数据长度))&
“秒。”);
端部平行加成试验;

是。这是安全的,因为不存在与读取数据相关的争用条件,也不存在临时重叠的写入操作。 例如,下面的代码使用这种技术对整数数组执行并行加法

package Parallel_Addition is
   type Data_Array is array(Integer range <>) of Integer;
   type Data_Access is access all Data_Array;
   function Sum(Item : in not null Data_Access) return Integer;
end Parallel_Addition;

package body Parallel_Addition is

   ---------
   -- Sum --
   ---------

   function Sum (Item : in not null Data_Access) return Integer is
      task type Adder is
         entry Set (Min : Integer; Max : Integer);
         entry Report (Value : out Integer);
      end Adder;

      task body Adder is
         Total : Integer := 0;
         First : Integer;
         Last  : Integer;
      begin
         accept Set (Min : Integer; Max : Integer) do
            First := Min;
            Last  := Max;
         end Set;
         for I in First .. Last loop
            Total := Total + Item (I);
         end loop;
         accept Report (Value : out Integer) do
            Value := Total;
         end Report;
      end Adder;
      A1  : Adder;
      A2  : Adder;
      R1  : Integer;
      R2  : Integer;
      Mid : constant Integer := (Item'Length / 2) + Item'First;
   begin
      A1.Set (Min => Item'First, Max => Mid);
      A2.Set (Min => Mid + 1, Max => Item'Last);
      A1.Report (R1);
      A2.Report (R2);
      return R1 + R2;
   end Sum;

end Parallel_Addition;

with Parallel_Addition; use Parallel_Addition;
with Ada.Text_IO;       use Ada.Text_IO;
with Ada.Calendar;      use Ada.Calendar;

procedure Parallel_Addition_Test is
   The_Data : Data_Access := new Data_Array (1 .. Integer'Last / 5);
   Start    : Time;
   Stop     : Time;
   The_Sum  : Integer;

begin
   The_Data.all := (others => 1);
   Start        := Clock;
   The_Sum      := Sum (The_Data);
   Stop         := Clock;
   Put_Line ("The sum is: " & Integer'Image (The_Sum));
   Put_Line
     ("Addition elapsed time is " &
      Duration'Image (Stop - Start) &
        " seconds.");
   Put_Line
     ("Time per addition operation is " &
        Float'Image(Float(Stop - Start) / Float(The_Data'Length)) &
        " seconds.");
end Parallel_Addition_Test;
package并行添加
类型数据_数组是整数的数组(整数范围);
类型Data\u Access为Access all Data\u数组;
函数和(项:在非空数据访问中)返回整数;
端部平行加成;
包体平行添加为
---------
--总数--
---------
函数和(项:在非空数据访问中)返回整数为
任务型加法器
条目集(最小值:整数;最大值:整数);
输入报告(值:out Integer);
末端加法器;
任务体加法器是
合计:整数:=0;
第一:整数;
最后:整数;
开始
接受集(最小值:整数;最大值:整数)do
第一:=Min;
最后:=最大值;
端集;
因为我是第一个。。最后一圈
总计:=总计+项目(I);
端环;
接受报告(值:out Integer)do
值:=总计;
结束报告;
末端加法器;
A1:加法器;
A2:加法器;
R1:整数;
R2:整数;
Mid:常量整数:=(项长度/2)+项首;
开始
A1.设置(最小值=>第一项,最大值=>中间值);
A2.设置(最小=>Mid+1,最大=>Item'Last);
A1.报告(R1);
A2.报告(R2);
返回R1+R2;
最终金额;
端部平行加成;
并行_加法;采用平行加法;
使用Ada.Text_IO;使用Ada.Text\u IO;
日历;使用Ada.Calendar;
程序并行加法测试
_数据:数据访问:=新数据数组(1..Integer'Last/5);
开始:时间;
停止:时间;
_和:整数;
开始
_Data.all:=(其他=>1);
开始:=时钟;
_总和:=总和(_数据);
停止:=时钟;
Put_行(“总和是:“&Integer”图像(总和));
放线
(“添加经过的时间为”&
持续时间图像(停止-启动)&
“秒。”);
放线
(“每次添加操作的时间为”&
浮动图像(浮动(停止-启动)/浮动(数据长度))&
“秒。”);
端部平行加成试验;

请注意,每个任务处理的字符串片段之间的预定义边界可能会有数字文字。啊,是的,上面的代码段只是一个粗略的表示,让您大致了解一下。实际的解析代码要复杂得多。如果您感兴趣,我正在解析OpenDDL请注意,您可能会有数字文本跨越每个任务处理的字符串片段之间的预定义边界。啊,是的,上面的代码段只是一个粗略的表示,让您了解一般的概念。实际的解析代码要复杂得多。如果您感兴趣,我将致力于解析OpenDDL