AdaPower Logged in as Guest
Ada Tools and Resources

Ada 95 Reference Manual
Ada Source Code Treasury
Bindings and Packages
Ada FAQ


Join >
Home >
Articles >
Getting Started >
Ada FAQ >
Source Treasury >
Books & Tutorials >
Packages for Reuse >
Latest Additions >
Ada Projects >
Press Releases >
Ada Audio / Video >
Home Pages >
Links >
Contact >
About >
Login >
Back
Batcher's Parallel Sort (Tom Moran)

This is an Ada implementation of Batcher's parallel sort from
Knuth.  The style is not nice since this was one of my earliest Ada
programs and it follows Knuth's algorithm description very closely.


--------------------------------------------------------------------------------


-- This is a simple implementation of Batcher's parallel sort, from
-- Knuth Volume 3, 5.2.2
--
-- It would be interesting to know the results of running it on a
-- machine with multiple processors, or a single shared processor
-- where multiple tasks give you a larger share of machine resources
-- than one task.  The test example is too small to do any more than
-- demonstrate that it runs.
--
-- There are three parts: par_sort specification, body, and par_test
-- separated by -----------------------
--
--    Copyright Tom Moran, 1988, 2000, anyone may use for any purpose.
--
-----------------------

package PAR_SORT is

-- Batcher's parallel method
-- Knuth 5.2.2

-- call procedure sort(n) with number of elements to be sorted
--
-- User must supply leq(i,j) => true iff i-th item <= j-th item
-- and exchange(i,j) to exchange i-th and j-th items.
-- i, j will always be in range 1..n
--
-- NOTE: leq and exchange must be re-entrant as they will be
-- called by simultaneously active tasks.
-- For leq, and separately for exchange, these multiple calls
-- will have disjoint i,j parameter pairs.  For a particular
-- pair, leq may be called, and after it has returned, exchange
-- may be called with the same pair of parameters.

    generic
        with function LEQ(I, J : POSITIVE) return BOOLEAN;
        with procedure EXCHANGE(I, J : in POSITIVE);
        -- instead of positive, i,j are really in 1..n, but we don't
        -- yet know n

        procedure SORT(N : in POSITIVE);

end PAR_SORT;

--------------------------

package body PAR_SORT is

    procedure SORT(N : in POSITIVE) is
        type mod_int is mod 32768;
        subtype POSITIONS is mod_int range 1 .. mod_int(N);

        P, Q, R, D, TWO_TO_T_MINUS_ONE : mod_int; -- see Knuth 5.2.2
                                                  -- we follow his notation

        task type ORDER_TASK is
            entry GET_PAIR(I, J : in POSITIONS);
        end ORDER_TASK;
        for ORDER_TASK'Storage_Size use 4096;

        task body ORDER_TASK is
            LOWER, HIGHER : POSITIONS;
        begin
            accept GET_PAIR(I, J : in POSITIONS) do
                LOWER := I; HIGHER := J;
            end GET_PAIR;

            if LEQ(positive(HIGHER), positive(LOWER)) then
              EXCHANGE(positive(LOWER), positive(HIGHER));
            end if;
        end ORDER_TASK;

    begin
        if N < 2 then return; end if;

        -- M1    (following Knuth)
        TWO_TO_T_MINUS_ONE := 1;
        while TWO_TO_T_MINUS_ONE < mod_int(N / 2) loop
            TWO_TO_T_MINUS_ONE := TWO_TO_T_MINUS_ONE * 2;
        end loop;
        P := TWO_TO_T_MINUS_ONE;
        -- M2
        while P > 0 loop
            Q := TWO_TO_T_MINUS_ONE;
            R := 0;
            D := P;
            -- M3
            loop -- until q = p

                declare
                    type ORDERER is access ORDER_TASK;
                    ORDER_A_PAIR : ORDERER;
                begin
                    for I in 0 .. mod_int(N) - D - 1 loop
                        if (I and  P) = R then
                            ORDER_A_PAIR := new ORDER_TASK;
                            ORDER_A_PAIR.GET_PAIR(I + 1, I + D + 1);
                        end if;
                    end loop; -- on i
                end; -- won't leave this block till all tasks have
terminated

                -- M5
                exit when Q = P;
                D := Q - P; Q := Q / 2; R := P;
            end loop; -- on q
            -- M6
            P := P / 2;
        end loop; -- on p

    end SORT;

end PAR_SORT;

---------------------

-- test Batcher's parallel sort routine using Knuth's example data

with PAR_SORT,
     Ada.TEXT_IO;
 use Ada.TEXT_IO;

procedure PAR_TEST is

    package INT_IO is new INTEGER_IO(INTEGER); use INT_IO;

    A : array (1 .. 16) of INTEGER :=
    (503,087,512,061,908,170,897,275,653,426,154,509,612,677,765,703);

    function LEQ(I, J : POSITIVE) return BOOLEAN is
    begin
        return (A(I) <= A(J));
    end LEQ;

    procedure EXCHANGE(I, J : in POSITIVE) is
        TEMP : INTEGER;
    begin
        TEMP := A(I); A(I) := A(J); A(J) := TEMP;
    end EXCHANGE;

    procedure TEST_SORT is new PAR_SORT.SORT(LEQ, EXCHANGE);

    procedure SHOW_A is
    begin
        for I in A'range loop
            PUT(A(I), WIDTH => 3);
            if I < A'LAST then PUT(","); end if;
        end loop;
        NEW_LINE;
    end SHOW_A;

begin

    SHOW_A;
    TEST_SORT(A'LENGTH);
    SHOW_A;

end PAR_TEST;


(c) 1998-2004 All Rights Reserved David Botton