Anwendungsbeispiel "Matrixmultiplikation in ADA95

 

Zum Programmcode


Der folgende Code zeigt ein Anwendungsbeispiel zum Ada-Paket Linda.
Das Wesentliche dabei ist, das Linda-Paket wie in Matrix.ads gezeigt einzubinden. Der dort erzeugte Typ Vector_Parameter_Type ist notwendig um den dort definierten Typ Vector_Type als Parameter für Linda-Tupel verwenden zu können.
Die Matrixmultiplikation verwendet Linda um die Berechnungsschritte zu parallelisieren. Dabei werden eine beliebige Anzahl von Tasks erzeugt, die die zu erledigenden Aufgaben durch die Linda-Primitive steuern. Die Prozedur selbst stellt die zu multiplizierenden Matrizen in Form von Zeilen und Spaltenvektoren in den Linda-Tupelraum, initialisiert die Berechnungsfolge und sammelt die Ergebnisse in beliebiger Reihenfolge ein. Die dort erzeugten Tasks holen sich die Vektoren aus dem Tupelraum, bilden das innere Produkt und geben das Ergebnis versehen mit der Position in der Ergebnismatrix in den Tupelraum aus. Die kursiv geschriebenen Kommentare stellen den einfachen Linda-Programmcode dar, der in Ada wegen der strengen Typsicherheit komplizierter ausprogrammiert werden muß.

 

Das ADA95-Programm

Matrix.ads

with Linda; use Linda;

package Matrix is

    type Vector_Type is array (1..3) of integer;
    function "*" (Left, Right: Vector_Type) return integer;

    type Matrix_Type is array (1..3) of Vector_Type;
    function "*" (Left, Right: Matrix_Type) return Matrix_Type;
    procedure Transpose (A: in Matrix_Type; B: out Matrix_Type);
    procedure print (M: Matrix_Type);

private

    type Vector_Parameter_Type
    is   new Parameter_Type
         with record
             V: Vector_Type;
         end record;

    function "=" (Left, Right: Vector_Parameter_Type) return boolean;

end Matrix;


Test.adb

with Matrix; use Matrix;

procedure Test is
begin
    print ( Matrix_Type'((1, 2, 3),
                         (4, 5, 6),
                         (7, 8, 9))
          * Matrix_Type'((2, 3, 4),
                         (5, 6, 7),
                         (8, 9, 10))
          );
end Test;

Matrix.adb - Matrixmupltiplikation

-- multipliziere zwei Matrizen und gebe das Ergebnis zurueck
function "*" (Left, Right: Matrix_Type) return Matrix_Type
is
    B, C: Matrix_Type;
    T   : Tuple_Type;
    It  : Iterator_Type;
    i, j: natural;

    -- Ein Inner_Producer harrt darauf, innere Produkte zu bilden
    task type Inner_Producer;

    -- Hier kann man beliebig viele Produzenten erzeugen
    Producers: array (1..5) of Inner_Producer;

    task body Inner_Producer
    is
        T: Tuple_Type;
        Element: natural;
        i, j: natural;
        V1, V2: Vector_Type;
    begin
        loop -- Input ("N", Element: integer)
             Empty (T);
             Add (T, Char_Parameter_Type'(false, 'N'));
             Add (T, Int_Parameter_Type'(true, 0));
             Input (T);
             Element := Int_Parameter_Type
                        (Value (Succ (First (T)))).Int;
             -- Output ("N", Element+1)
             Empty (T);
             Add (T, Char_Parameter_Type'(false, 'N'));
             Add (T, Int_Parameter_Type'(false, Element + 1));
             Output (T);
        exit when Element > 3 * 3;
             -- Zeile und Spalte ermitteln
             i := (Element - 1) / 3 + 1;
             j := (Element - 1) mod 3 + 1;
             -- Read ("A", i, V1: Vector)
             Empty (T);
             Add (T, Char_Parameter_Type'(false, 'A'));
             Add (T, Int_Parameter_Type'(false, i));
             Add (T, Vector_Parameter_Type'(true, (others => 0)));
             Read (T);
             V1 := Vector_Parameter_Type
                   (Value (Succ (Succ (First (T))))).V;
             -- Read ("B", j, Vector)
             Empty (T);
             Add (T, Char_Parameter_Type'(false, 'B'));
             Add (T, Int_Parameter_Type'(false, j));
             Add (T, Vector_Parameter_Type'(true, (others => 0)));
             Read (T);
             V2 := Vector_Parameter_Type
                   (Value (Succ (Succ (First (T))))).V;
             -- Output ("C", i, j, V1 * V2)
             Empty (T);
             Add (T, Char_Parameter_Type'(false, 'C'));
             Add (T, Int_Parameter_Type'(false, i));
             Add (T, Int_Parameter_Type'(false, j));
             Add (T, Int_Parameter_Type'(false, V1 * V2));
             Output (T);
        end loop;
    end Inner_Producer;


begin
    -- Die zweite Matrix transponieren, um Spaltenvektoren zu erhalten
    Transpose (Right, B);
    -- Die Vektoren der beiden Matrizen ausgeben
    for  i in 1..3
    loop -- Output ("A", i, Zeilenvektor)
         Empty (T);
         Add (T, Char_Parameter_Type'(false, 'A'));
         Add (T, Int_Parameter_Type'(false, i));
         Add (T, Vector_Parameter_Type'(false, Left (i)));
         Output (T);
    end loop;
    for  i in 1..3
    loop -- Output ("B", i, Spaltenvektor)
         Empty (T);
         Add (T, Char_Parameter_Type'(false, 'B'));
         Add (T, Int_Parameter_Type'(false, i));
         Add (T, Vector_Parameter_Type'(false, B (i)));
         Output (T);
    end loop;
    -- Output ("N", 1)
    Empty (T);
    Add (T, Char_Parameter_Type'(false, 'N'));
    Add (T, Int_Parameter_Type'(false, 1));
    Output (T);
    -- Ergebnisse sammeln
    for  k in 1..3*3
    loop -- Input ("C", i: integer, j: integer, c)
         Empty (T);
         Add (T, Char_Parameter_Type'(false, 'C'));
         Add (T, Int_Parameter_Type'(true, 0)):
         Add (T, Int_Parameter_Type'(true, 0));
         Add (T, Int_Parameter_Type'(true, 0));
         Input (T);
         It := Succ (First (T));
         i := Int_Parameter_Type (Value (It)).Int;
         It := Succ (It);
         j := Int_Parameter_Type (Value (It)).Int;
         -- C (i) (j) := c
         It := Succ (It);
         C (i) (j) := Int_Parameter_Type (Value (It)).Int;
    end loop;
    return C;
end "*";


Testlauf

$ test
  36  42  48
  81  96 111
 126 150 174
$ _