2017-01-06 5 views
1

私は現在、プロシージャ内で2つのタスクを作成して、それぞれのプロシージャに渡される配列の数を追加しています。Outパラメータが定義されていません

私の一般的なパッケージには、次のようになります。

generic 
    type Item_Type is private; 
    with function "+"(Left: Item_Type; Right: Item_Type) return Item_Type; 
package Parallel_Algorithms is 

    type Array_Type is array(Natural range <>) of Item_Type; 
    type Array_Access_Type is access all Array_Type; 

    procedure Parallel_Sum(Input: Array_Access_Type; Result: out Item_Type); 

end Parallel_Algorithms; 

私は実装が完璧ではないことを意識すること、Parallel_Sumメソッドに以下の方法を実施し、またスレッドセーフ。

procedure Parallel_Sum(Input: Array_Access_Type; Result: out Item_Type) is 

    Loop_Var: Integer:= 0; 

    task type T; 
    Task1, Task2 : T; 

    task body T is 
     begin 
      while Loop_Var < Input'Length loop 
       Result := Result + Input(Loop_Var); 
       Loop_Var := Loop_Var + 1; 
     end loop; 
    end T; 

begin 
    -- Result := Temp; 
end Parallel_Sum; 

私は今Resultの出力は常にその結果が明らかに間違っている(1,2,3,4)私の配列の内部の要素を考慮し1918988326.のようなものされて終わる私のメインプログラムを実行する場合。

アウトタイプを変更しないと、それぞれの変数の動作が未定義になることがあります。

「本当の」Resultを取得する適切な方法は何ですか?

+0

あなたのタスク体ループはすべて間違っています。配列の長さにわたって、インデックス値の範囲を超えて反復していません。 –

+0

パラメータを に変更できます。入力タイプは<>です。 これは、Input_Typeを整数型に強制します。 "+"関数を渡す必要はありません。 –

+0

私はあなたが何を意味しているのか理解していますが、私は両方のタスクを開始し、それぞれが現在のインデックスの値を結果に追加することを考えました。これを行うことで、Loop_Varがリストの長さに等しい時点で完全な結果が得られ、ループはタスクと同様に終了するでしょうか? – hGen

答えて

4

問題をより詳しく見ると、克服すべきいくつかの問題があることがわかります。タスクは自分の合計を累積しなければなりません。保護されていない結果変数に合計を追加すると、結果が未定義になる競合条件が生成されます。

この問題に対する私のアプローチは次のとおりです。

------------------------------------------------------------------ 
-- Parallel Addition of Array Elements -- 
------------------------------------------------------------------ 
generic 
    type Element_Type is range <>; 
package Parallel_Addition is 
    type Array_Type is array(Natural range <>) of Element_Type; 
    type Array_Access is access all Array_Type; 

    task type Adder is 
     Entry Set_Slice(Low, High : in Natural; 
         Item : in not null Array_Access); 
    end Adder; 

    protected Result is 
     procedure Accumulate(Item : in Element_Type); 
     function Report return Element_Type; 
    private 
     Sum : Integer := 0; 
    end Result; 

end Parallel_Addition; 
package body Parallel_Addition is 

    ----------- 
    -- Adder -- 
    ----------- 

    task body Adder is 
     My_Array  : Array_Access; 
     Id_Low, Id_High : Natural; 
     Sum    : Integer := 0; 
    begin 
     accept Set_Slice(Low, High : in Natural; 
         Item : in not null Array_Access) do 
     Id_Low := Low; 
     Id_High := High; 
     My_Array := Item; 
     end Set_Slice; 
     for I in Id_Low..Id_High loop 
     Sum := Sum + Integer(My_Array(I)); 
     end loop; 
     Result.Accumulate(Element_Type(Sum)); 
    end Adder; 

    ------------ 
    -- Result -- 
    ------------ 

    protected body Result is 

     ---------------- 
     -- Accumulate -- 
     ---------------- 

     procedure Accumulate (Item : in Element_Type) is 
     begin 
     Sum := Sum + Integer(Item); 
     end Accumulate; 

     ------------ 
     -- Report -- 
     ------------ 

     function Report return Element_Type is 
     begin 
     return Element_Type(Sum); 
     end Report; 

    end Result; 

end Parallel_Addition; 
------------------------------------------------------------------ 
-- Parallel_Addition Test -- 
------------------------------------------------------------------ 
with Ada.Text_IO; use Ada.Text_IO; 
with Parallel_Addition; 

procedure PA_Test is 
    package adders is new Parallel_Addition(Natural); 
    use adders; 
    Data : aliased Array_Type := (1,2,3,4,5,6,7,8,9,10); 
    T1, T2 : Adder; 
begin 
    T1.Set_Slice(Low => 0, High => 4, Item => Data'Access); 
    T2.Set_Slice(Low => 5, High => 9, Item => Data'Access); 
    loop 
     if T1'Terminated and then T2'Terminated then 
     exit; 
     end if; 
    end loop; 
    put_Line("The sum is " & Integer'Image(Result.Report)); 
end PA_Test; 
関連する問題