Ada同步-如何使代码更快?

问题描述

受保护对象机制不仅可以用于共享数据,还可以用于同步 动作。这是一种(尝试)同步所有任务并释放所有任务的模式 一旦所有任务准备就绪即可进行。条目上的Count属性可方便地用于此目的,因为它指示当前在此特定条目上等待的任务数。在这里我们打开 条目根据等待的任务数量进行同步:

with Ada.Task_Identification; use Ada.Task_Identification;
with Ada.Text_IO; use Ada.Text_IO;
procedure Synchronized_Action is
 No_Of_Tasks : constant Positive := 5;
 protected type Blockers (Group_Size : Positive) is
 entry Synchronize;
 end Blockers;
 protected body Blockers is
 entry Synchronize when Synchronize’Count = Group_Size is
 begin
 null;
 end Synchronize;
 end Blockers;
 Blocker : Blockers (No_Of_Tasks);
 task type In_Synchronized_Stages;
 task body In_Synchronized_Stages is
 begin
 Put_Line (“Task “ & Image (Current_Task) & “ starting up”);
 delay 1.0;
 Blocker.Synchronize;
 Put_Line (“Task “ & Image (Current_Task) & “ in stage 1”);
 delay 1.0;
 Blocker.Synchronize;
 Put_Line (“Task “ & Image (Current_Task) & “ in stage 2”);
 end In_Synchronized_Stages;
 Staged_Tasks : array (1 .. No_Of_Tasks) of In_Synchronized_Stages;
begin
 null;
end Synchronized_Action;

现在我不得不承认这个程序看起来比运行的更好:它“挂起”-或至少看起来像 除了最耐心的用户外,所有其他用户都无法使用。该程序的思想是,所有任务在各个阶段之间重新同步,这样,任何任务都不应在以后的阶段中完成所有工作,而其他任务 早期阶段任务仍然很忙。 修复此程序,使其确实显示预期的行为并运行完毕。 提示:您期望在屏幕上看到输出的时间顺序是什么?什么 实际输出的节奏是什么?这怎么可能发生? … 现在轮到你 显示看到错误(对吗?)并可以修复它。

以下实现确实可以完成,但是大约需要0.5秒。可以做些什么来使其更快?

with Ada.Task_Identification; use Ada.Task_Identification;
with Ada.Text_IO;             use Ada.Text_IO;

procedure Synchronized_Action is

   No_Of_Tasks : constant Positive := 5;

   protected type Blockers (Group_Size : Positive) is

      entry Synchronize;
   private
      Triggered : Boolean := False;

   end Blockers;

   protected body Blockers is

      entry Synchronize when Synchronize'Count = Group_Size or Triggered is

      begin
         if Synchronize'Count = 0 then
            Triggered := False;
         else
            Triggered := True;
         end if;
      end Synchronize;

   end Blockers;

   Blocker : Blockers (No_Of_Tasks);

   task type In_Synchronized_Stages;

   task body In_Synchronized_Stages is

   begin
      Put_Line ("Task " & Image (Current_Task) & " starting up");
      delay 0.0;

      Blocker.Synchronize;

      Put_Line ("Task " & Image (Current_Task) & " in stage 1");
      delay 0.0;

      Blocker.Synchronize;

      Put_Line ("Task " & Image (Current_Task) & " in stage 2");

   end In_Synchronized_Stages;

   Staged_Tasks : array (1 .. No_Of_Tasks) of In_Synchronized_Stages; pragma Unreferenced (Staged_Tasks);

begin
   null;
end Synchronized_Action;

解决方法

与您在other question中遇到的困难相比,这是相当复杂的代码,所以我想知道它们是否是课堂问题,即家庭作业?

第一个版本失败的原因是每次激活后都会重新评估输入条件,因此当第一个任务完成时,输入队列中只有4个任务。

无论如何,如果排队策略(ARM D.4)不是FIFO_Queuing,那么我不禁觉得第二版可能存在相关问题。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...