comp.lang.ada
 help / color / mirror / Atom feed
From: tmoran@acm.org
Subject: Re: Gnat 3.15p & Windows & Hyperthreading Q
Date: Sat, 26 Mar 2005 12:36:20 -0600
Date: 2005-03-26T12:36:20-06:00	[thread overview]
Message-ID: <DPadnZq_15c5NtjfRVn-oQ@comcast.com> (raw)
In-Reply-To: rPd1e.9183$S46.1228@newsread3.news.atl.earthlink.net

> >   I'm told that a multitask program compiled with Gnat 3.15p and run
> > under Windows XP Pro on a hyperthreaded machine, runs in the same total
> > time as the same program using a single task.  OTOH, when compiled with
> > GNAT 5.02a1 and run on a dual-processor 400 MHz Celeron running Mandrake
> > Linux 8.2, it runs about 50% faster with two rather than one tasks.
>
> That seems strange. In the first case, is it a SINGLE processor machine?
> Or is it the same dual processor 400mhz Celeron in both cases?
> Also, is this just anecdotal or is there an actual benchmark program
> that could be looked at?
    The original program was posted under "Ada bench : count words",
as was the dual-Celeron timing.  The hyperthreading timing was a personal
communication.  It's possible the person was mistaken in thinking they
had hyperthreading turned on, with processor affinities set correctly.
I'm inquiring further.

  So here's the benchmark.  It reads a text file from Standard Input,
preferably at least a megabyte to get a decent timing read, and prints
line, word, and character counts to Standard Output.  The number of
CPU-heavy tasks is the number of elements of
  Counter : array(1 .. 2) of Counters;
Probably increasing the buffer size, by lessening task interactions,
would speed it up and improve the multi-tasking benefit.

with Ada.Calendar,
     Ada.Streams,
     Ada.Streams.Stream_IO,
     Ada.Text_IO,
     Ada.Text_IO.Text_Streams;
procedure Cwt is
  use Ada.Streams;
  use type Ada.Calendar.Time;

  T0  : Ada.Calendar.Time := Ada.Calendar.Clock;  -- start timing
  T1  : Ada.Calendar.Time;

  subtype Buffer_Type is Stream_Element_Array(1 .. 4096);

  LF      : constant Stream_Element := Character'pos(Ascii.LF);
  Is_Whitespace : constant array(Stream_Element) of Boolean
    := (Character'pos(Ascii.LF) | Character'pos(Ascii.HT)
        | Character'pos(' ') => True, others => False);

  -- "Counters" tasks run independently, asking Data_Source for buffer loads
  -- and tallying word and line counts.  When done, they wait for their
  -- (partial) counts to be harvested, then terminate.

  task type Counters is
    entry Harvest(Line_Count, Word_Count : out Natural);
  end Counters;

  -- Data_Source is the IO task, supplying data as requested to Counters.
  -- Note that Data_Source counts the whitespace->non-white transitions
  -- at the ends of buffers.  Counters' partial counts are added to that.
  -- Data_Source also counts the Total number of characters.

  task Data_Source is
    entry Get(Buffer : out Buffer_Type;
              Last : out Stream_Element_Offset);
  end Data_Source;

  task body Counters is
    Buffer : Buffer_Type;
    Last : Stream_Element_Offset;
    Lines, Words, Total : Natural := 0;
    In_Whitespace : Boolean;
  begin
    loop
      Data_Source.Get(Buffer, Last);
      exit when Last = 0;
      In_Whitespace := Is_Whitespace(Buffer(1));
      for I in 1 .. Last loop
        if Is_Whitespace(Buffer(I)) then
          if Buffer(I) = LF then
            Lines := Lines + 1;
          end if;
          In_Whitespace := True;
        elsif In_Whitespace then
          In_Whitespace := False;
          Words := Words + 1;
        end if;
      end loop;
      exit when Last < Buffer'last;
    end loop;
    accept Harvest(Line_Count, Word_Count : out Natural) do
      Line_Count := Lines;
      Word_Count := Words;
    end;
  end Counters;

  Lines, Words, Total : Natural := 0;

  task body Data_Source is
    Stream  : Ada.Text_IO.Text_Streams.Stream_Access;
    At_End : Boolean := False;
    In_Whitespace : Boolean := True; -- we must count at edges of buffer loads
  begin
    Stream := Ada.Text_IO.Text_Streams.Stream(Ada.Text_IO.Current_Input);
    loop
      select
        accept Get(Buffer : out Buffer_Type;
                   Last : out Stream_Element_Offset) do
          if At_End then Last := 0;
          else
            Ada.Streams.Read(Ada.Streams.Root_Stream_Type'Class(Stream.all),
                             Buffer, Last);
            Total := Total+Integer(Last);
            if Last > 0 then
              if In_Whitespace and not Is_Whitespace(Buffer(1)) then
                Words := Words+1;
              end if;
              In_Whitespace := Is_Whitespace(Buffer(Last));
            end if;
            if Last < Buffer'last then At_End := True;end if;
          end if;
        end;
      or terminate;
      end select;
    end loop;
  end Data_Source;

  A_Line_Count, A_Word_Count : Natural := 0;

  Counter : array(1 .. 2) of Counters;

begin

  for i in Counter'range loop
    Counter(i).Harvest(A_Line_Count, A_Word_Count);
    Lines := Lines+A_Line_Count;
    Words := Words+A_Word_Count;
  end loop;

  T1 := Ada.Calendar.Clock;

  Ada.Text_IO.Put_Line(Natural'Image(Lines)
                       & Natural'Image(Words)
                       & Natural'Image(Total));
  Ada.Text_IO.Put_Line("took" & Duration'Image(T1 - T0));
end Cwt;



  reply	other threads:[~2005-03-26 18:36 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-03-26  0:28 Gnat 3.15p & Windows & Hyperthreading Q tmoran
2005-03-26  4:45 ` Steve
2005-03-26  9:41 ` Pascal Obry
2005-03-26 13:53 ` Marin David Condic
2005-03-26 18:36   ` tmoran [this message]
2005-03-28 13:16     ` Marin David Condic
2005-03-27 11:27   ` Simon Wright
2005-03-29 18:33 ` Wiljan Derks
2005-03-30  8:48   ` Adrien Plisson
2005-04-01  7:09     ` tmoran
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox