comp.lang.ada
 help / color / mirror / Atom feed
* can someone help me with this code (explanation)
@ 2014-09-25 13:44 Stribor40
  2014-09-25 14:56 ` Björn Lundin
  2014-09-25 16:53 ` Jeffrey Carter
  0 siblings, 2 replies; 30+ messages in thread
From: Stribor40 @ 2014-09-25 13:44 UTC (permalink / raw)


Can someone help me understand this code which is from tutorial found here...
http://infres.enst.fr/~pautet/Ada95/chap27.htm and code is here
http://infres.enst.fr/~pautet/Ada95/e_c27_p3.ada

If we assume John task starts first...first time trough the loop John does Gourmet.Make_A_Hot_Dog(Index, TRUE);
which blocks him and Goutmet starts running so once Gourmet stops John continues does Bill calls Gourmet and John wait in the queue in his second loop?


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-25 13:44 can someone help me with this code (explanation) Stribor40
@ 2014-09-25 14:56 ` Björn Lundin
  2014-09-25 15:01   ` Björn Lundin
  2014-09-25 15:54   ` Stribor40
  2014-09-25 16:53 ` Jeffrey Carter
  1 sibling, 2 replies; 30+ messages in thread
From: Björn Lundin @ 2014-09-25 14:56 UTC (permalink / raw)


On 2014-09-25 15:44, Stribor40 wrote:
> Can someone help me understand this code which is from tutorial found here...
> http://infres.enst.fr/~pautet/Ada95/chap27.htm and code is here
> http://infres.enst.fr/~pautet/Ada95/e_c27_p3.ada
> 
> If we assume John task starts first...first time trough the loop John does Gourmet.Make_A_Hot_Dog(Index, TRUE);
> which blocks him and Goutmet starts running so once Gourmet stops John continues does Bill calls Gourmet and John wait in the queue in his second loop?
> 

Bill and John starts
asking Gourmet to make them a hotdog, one at a time.
The order between them is not determined.
Gourmet has 5 hotdogs available and Bill will ask 3 times while john
asks 2 times.

As soon as Gourmet has accepted Bill's or John's
request, Gourmet is busy, so whoever will ask next
has to wait.

the order might be

Bill
John
Bill
John
Bill

or

John
Bill
John
Bill
Bill


but also (perhaps not likely)
Bill
Bill
Bill
John
John

Any combination is valid. (os and/or task priorities affects this)
But likely the other tasks gets to line up in
the select statement of Gourmet
before the served task can make a new request.


Once gourmet has served 5 times, it will not accept anything else,
since it exits the loop. It will then terminate.

Likewise for Bill and John.
After they requsted their food, they will exit their loop
and terminate.


Once all tasks are terminated, the program itself will stop/terminate.

--
Björn


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-25 14:56 ` Björn Lundin
@ 2014-09-25 15:01   ` Björn Lundin
  2014-09-25 15:54   ` Stribor40
  1 sibling, 0 replies; 30+ messages in thread
From: Björn Lundin @ 2014-09-25 15:01 UTC (permalink / raw)


On 2014-09-25 16:56, Björn Lundin wrote:
> But likely the other tasks gets to line up in
> the select statement of Gourmet
> before the served task can make a new request.

But likely the other tasks gets to line up in
the ACCEPT statement of Gourmet
before the served task can make a new request.

And I think it would be better if Johns index went from 4 ..5
so they did not overlap.


-- Result of execution

-- I am ready to make a hot dog for you
-- Put hot dog number 1 in bun and add mustard       <-- call from John
-- Put hot dog number 1 in bun and hold the mustard  <-- call from Bill


--
Björn


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-25 14:56 ` Björn Lundin
  2014-09-25 15:01   ` Björn Lundin
@ 2014-09-25 15:54   ` Stribor40
  2014-09-25 17:11     ` Niklas Holsti
  1 sibling, 1 reply; 30+ messages in thread
From: Stribor40 @ 2014-09-25 15:54 UTC (permalink / raw)


Why would this one even be possible....

Bill
Bill
Bill
John
John 

If say Bill starts first...as soon as he enters John will be in queue....
As soon as Gourmet is done Bill continues and John calls Gourmet so how would we even get to

Bill
Bill
...


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-25 13:44 can someone help me with this code (explanation) Stribor40
  2014-09-25 14:56 ` Björn Lundin
@ 2014-09-25 16:53 ` Jeffrey Carter
  1 sibling, 0 replies; 30+ messages in thread
From: Jeffrey Carter @ 2014-09-25 16:53 UTC (permalink / raw)


On 09/25/2014 06:44 AM, Stribor40 wrote:
> 
> If we assume John task starts first...first time trough the loop John does
> Gourmet.Make_A_Hot_Dog(Index, TRUE); which blocks him and Goutmet starts
> running so once Gourmet stops John continues does Bill calls Gourmet and John
> wait in the queue in his second loop?

Gourmet, Bill, and John all start at the same time. While Gourmet is printing
its welcome message, Bill and John call Gourmet's entry Make_A_Hot_Dog and are
blocked until Gourmet accepts the entry call. Whichever is first in the entry
queue is largely a matter of chance.

That is how you should think about this. If you have a computer that can run 3
or more tasks at the same time (which describes many modern computers with 2 or
more cores) then it is also what happens. Even on a monoprocessor only able to
run 1 task at a time what will happen will be very close to this, since Gourmet
should block waiting for I/O and the eater tasks should block on the entry call,
so you end up with both eaters in the queue and Gourmet reaching its accept for
the 1st time.

-- 
Jeff Carter
"Blessed is just about anyone with a vested interest in the status quo."
Monty Python's Life of Brian
73


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-25 15:54   ` Stribor40
@ 2014-09-25 17:11     ` Niklas Holsti
  2014-09-25 19:41       ` Stribor40
  0 siblings, 1 reply; 30+ messages in thread
From: Niklas Holsti @ 2014-09-25 17:11 UTC (permalink / raw)


On 14-09-25 18:54 , Stribor40 wrote:
> Why would this one even be possible....

It is possible in principle, because of promises that are absent from
the Ada language standard, but quite unlikely in practice, in any real
Ada implementation. (However, in more complex programs, with less clear
task timing, similar things can be more likely even in practice.)

> Bill
> Bill
> Bill
> John
> John 
> 
> If say Bill starts first...as soon as he enters John will be in queue....

John may not yet be in the queue, for two reasons, the first one
possibly true in practice:

- First reason: If your computer has only one core processor, and this
core can run only one task at a time (common in the past, less common
now), the core may run Gourmet first, until she enters the accept
statement, then run Bill until he calls Make_A_Hot_Dog, then run Gourmet
again up to the delay statement, giving John no chance to execute and
reach his call of Make_A_Hot_Dog. This can happen in practice. However,
in practice, when Gourmet executes the delay statement the core will
start running John until he calls Make_A_Hot_Dog and enters the queue.

- Second reason: In principle, the Ada language standard makes no
promises about task execution speed. John may take as long as he pleases
to reach his first Make_A_Hot_Dog call - John can be so slow that Bill
gets and eats all his hot dogs before John orders his first one. This is
very unlikely in this example program, but such things can happen in
practice in larger programs if there are other tasks with a priority
higher than John's priority, but lower than the priorities of Bill and
Gourmet.

By the way, using Ada.Text_IO from multiple tasks without
synchronisation, on the same file (Standard_Output), is not to be
recommended -- such use of Ada.Text_IO is not "task safe", I believe.
However, Put_Line and similar simple things usually work with GNAT
Text_IO from multiple tasks.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
      .      @       .


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-25 17:11     ` Niklas Holsti
@ 2014-09-25 19:41       ` Stribor40
  2014-09-25 19:53         ` Jeffrey Carter
  2014-09-25 20:10         ` Niklas Holsti
  0 siblings, 2 replies; 30+ messages in thread
From: Stribor40 @ 2014-09-25 19:41 UTC (permalink / raw)


is.... I am ready to make a hot dog for you

first line of the output text always regardless how many cpu?


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-25 19:41       ` Stribor40
@ 2014-09-25 19:53         ` Jeffrey Carter
  2014-09-25 20:10         ` Niklas Holsti
  1 sibling, 0 replies; 30+ messages in thread
From: Jeffrey Carter @ 2014-09-25 19:53 UTC (permalink / raw)


On 09/25/2014 12:41 PM, Stribor40 wrote:
> is.... I am ready to make a hot dog for you
> 
> first line of the output text always regardless how many cpu?

Should be. There's no way for a task to get to another output statement until
that one has completed.

-- 
Jeff Carter
"Blessed is just about anyone with a vested interest in the status quo."
Monty Python's Life of Brian
73


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-25 19:41       ` Stribor40
  2014-09-25 19:53         ` Jeffrey Carter
@ 2014-09-25 20:10         ` Niklas Holsti
  2014-09-25 22:27           ` Jeffrey Carter
  2014-09-26  5:06           ` J-P. Rosen
  1 sibling, 2 replies; 30+ messages in thread
From: Niklas Holsti @ 2014-09-25 20:10 UTC (permalink / raw)


On 14-09-25 22:41 , Stribor40 wrote:
> is.... I am ready to make a hot dog for you
> 
> first line of the output text always regardless how many cpu?

It is guaranteed that the first call of Ada.Text_IO.Put_Line will be
that call, because Bill and John call Put_Line only after getting their
hot-dogs from Gourmet, after calling and returning from Make_A_Hot_Dog.

The rendez-vous at the accept statement in Gourmet synchronises the
order of execution of the statements in the tasks (well, in the calling
task and the accepting task; as has already been said, the execution
progress of other tasks, at that time, cannot be predicted in general).
Each task executes its statements sequentially, but the relative order
of execution in different tasks is known only at such synchronisation
points.

It is not guaranteed, as I understand it, that the text string "I am
ready to make a hot dog for you" will appear intact on your screen,
because Ada.Text_IO is not meant to be used concurrently from several
tasks, on the same file (here, Standard_Output). In practice, it
probably will appear on your screen.

To make task-safe use of Ada.Text_IO, it should be wrapped in some way
to ensure that only one task calls it at a time. For example, you could
write a task with an entry like Put_Line (Message : in String) and an
accept statement that does Ada.Text_IO.Put_Line (Message). But a
protected-object wrapper is probably better for uses where I/O
performance (latency) is not critical.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
      .      @       .


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-25 20:10         ` Niklas Holsti
@ 2014-09-25 22:27           ` Jeffrey Carter
  2014-09-26  7:04             ` Björn Lundin
  2014-09-26 16:44             ` Niklas Holsti
  2014-09-26  5:06           ` J-P. Rosen
  1 sibling, 2 replies; 30+ messages in thread
From: Jeffrey Carter @ 2014-09-25 22:27 UTC (permalink / raw)


On 09/25/2014 01:10 PM, Niklas Holsti wrote:
> 
> To make task-safe use of Ada.Text_IO, it should be wrapped in some way
> to ensure that only one task calls it at a time. For example, you could
> write a task with an entry like Put_Line (Message : in String) and an
> accept statement that does Ada.Text_IO.Put_Line (Message). But a
> protected-object wrapper is probably better for uses where I/O
> performance (latency) is not critical.

Except that I/O is potentially blocking, and so cannot appear in a protected
operation, meaning one needs a task one way or another.

-- 
Jeff Carter
"Blessed is just about anyone with a vested interest in the status quo."
Monty Python's Life of Brian
73


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-25 20:10         ` Niklas Holsti
  2014-09-25 22:27           ` Jeffrey Carter
@ 2014-09-26  5:06           ` J-P. Rosen
  1 sibling, 0 replies; 30+ messages in thread
From: J-P. Rosen @ 2014-09-26  5:06 UTC (permalink / raw)


Le 25/09/2014 22:10, Niklas Holsti a écrit :
> To make task-safe use of Ada.Text_IO, it should be wrapped in some way
> to ensure that only one task calls it at a time. For example, you could
> write a task with an entry like Put_Line (Message : in String) and an
> accept statement that does Ada.Text_IO.Put_Line (Message). But a
> protected-object wrapper is probably better for uses where I/O
> performance (latency) is not critical.
Except that IO operations are potentially blocking, and thus not allowed
in protected operations (although they are known to work with Gnat).

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-25 22:27           ` Jeffrey Carter
@ 2014-09-26  7:04             ` Björn Lundin
  2014-09-26  7:58               ` J-P. Rosen
  2014-09-26 16:44             ` Niklas Holsti
  1 sibling, 1 reply; 30+ messages in thread
From: Björn Lundin @ 2014-09-26  7:04 UTC (permalink / raw)


On 2014-09-26 00:27, Jeffrey Carter wrote:
> On 09/25/2014 01:10 PM, Niklas Holsti wrote:
>>
>> To make task-safe use of Ada.Text_IO, it should be wrapped in some way
>> to ensure that only one task calls it at a time. For example, you could
>> write a task with an entry like Put_Line (Message : in String) and an
>> accept statement that does Ada.Text_IO.Put_Line (Message). But a
>> protected-object wrapper is probably better for uses where I/O
>> performance (latency) is not critical.
> 
> Except that I/O is potentially blocking, and so cannot appear in a protected
> operation, meaning one needs a task one way or another.
> 
Or by using a protected object as a semaphore



   protected type Semaphore_Type is
      procedure Release;
      entry Seize;
   private
      In_Use : Boolean := False;
   end Semaphore_Type;

   protected body Semaphore_Type is
      procedure Release is
      begin
         In_Use := False;
      end;
      entry Seize when not In_Use is
      begin
         In_Use := True;
      end;
   end Semaphore_Type;

  Semaphore : Semaphore_Type;


  procedure Do_Safe_Put_Line(What : String) is
  begin
    Semaphore.Seize;
    Ada.Text_Io.Put_Line(What);
    Semaphore.Release;
  end Do_Safe_Put_Line;

  procedure Do_Safe_Put(What : String) is
  begin
    Semaphore.Seize;
    Ada.Text_Io.Put(What);
    Semaphore.Release;
  end Do_Safe_Put;



Using Do_Safe_Put or Do_Safe_Put_Line
can be used by any of the tasks.

If several tries to use them at the same time,
they will line up in the Seize statement,
and go ahead whe the task holding the semaphor calls Release.


--
Björn


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-26  7:04             ` Björn Lundin
@ 2014-09-26  7:58               ` J-P. Rosen
  2014-09-26 10:24                 ` G.B.
                                   ` (2 more replies)
  0 siblings, 3 replies; 30+ messages in thread
From: J-P. Rosen @ 2014-09-26  7:58 UTC (permalink / raw)


Le 26/09/2014 09:04, Björn Lundin a écrit :
> Or by using a protected object as a semaphore
>
But why? It's so simpler with a task:

   task Printer is
      entry Print (Mess : String);
   end Printer;

   task body Printer is
      use Text_IO;
   begin
      loop
         select
            accept Print (Mess : String) do
               Put_Line (Mess);
            end Print;
         or terminate;
         end select;
      end loop;
   end Printer;


-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-26  7:58               ` J-P. Rosen
@ 2014-09-26 10:24                 ` G.B.
  2014-09-26 11:48                 ` Björn Lundin
  2014-09-26 16:45                 ` Niklas Holsti
  2 siblings, 0 replies; 30+ messages in thread
From: G.B. @ 2014-09-26 10:24 UTC (permalink / raw)


On 26.09.14 09:58, J-P. Rosen wrote:
> Le 26/09/2014 09:04, Björn Lundin a écrit :
>> Or by using a protected object as a semaphore
>>
> But why? It's so simpler with a task:

It also centralizes I/O to one task, unlike a solution using
locking in each task that takes hold of a PO or, alternatively,
a Suspension_Object:

    procedure Print (Message : String) is
       use Ada.Text_IO, Ada.Synchronous_Task_Control;
    begin
       Suspend_Until_True (Lock);
       Put_Line (Message);
       Flush;
       Set_True (Lock);
    end Print;



^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-26  7:58               ` J-P. Rosen
  2014-09-26 10:24                 ` G.B.
@ 2014-09-26 11:48                 ` Björn Lundin
  2014-09-26 12:49                   ` J-P. Rosen
  2014-09-26 16:45                 ` Niklas Holsti
  2 siblings, 1 reply; 30+ messages in thread
From: Björn Lundin @ 2014-09-26 11:48 UTC (permalink / raw)


On 2014-09-26 09:58, J-P. Rosen wrote:
> Le 26/09/2014 09:04, Björn Lundin a écrit :
>> Or by using a protected object as a semaphore
>>
> But why? It's so simpler with a task:

Yes. But

Some people in this group likes to optimize code.
Having a render-vouz between two tasks, I think,
is more expensive that calling a protected object.

Personally, I'd go for the serializing task model, as
you propose.


The post was mere a reflection over Niklas'
solution, and Jeffrey's correct objection
over blocking I/O in protected objects


--
Björn


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-26 11:48                 ` Björn Lundin
@ 2014-09-26 12:49                   ` J-P. Rosen
  2014-09-26 14:15                     ` Björn Lundin
  0 siblings, 1 reply; 30+ messages in thread
From: J-P. Rosen @ 2014-09-26 12:49 UTC (permalink / raw)


Le 26/09/2014 13:48, Björn Lundin a écrit :
> Some people in this group likes to optimize code.
> Having a render-vouz between two tasks, I think,
> is more expensive that calling a protected object.
Hmm... Anything related to efficiency should be backed by measurements.
But my wild guess is that it would likely make a difference on bare
boards, but not on native operating systems.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-26 12:49                   ` J-P. Rosen
@ 2014-09-26 14:15                     ` Björn Lundin
  2014-09-26 14:49                       ` J-P. Rosen
  2014-09-26 16:43                       ` Niklas Holsti
  0 siblings, 2 replies; 30+ messages in thread
From: Björn Lundin @ 2014-09-26 14:15 UTC (permalink / raw)


On 2014-09-26 14:49, J-P. Rosen wrote:
> Le 26/09/2014 13:48, Björn Lundin a écrit :
>> Some people in this group likes to optimize code.
>> Having a render-vouz between two tasks, I think,
>> is more expensive that calling a protected object.

> Hmm... Anything related to efficiency should be backed by measurements.

http://www.sigada.org/conf/sa98/papers/mueller.pdf

I did not read all of it, but the conclusion is that
context switches are bad for performance.
If a protected object can REPLACE a task, it
will show in measurements. (and they did measure)

However, it is tested with gnat 3.10,
so things might be different now.

And I now learned that render-vouz is spelled rendezvous


--
Björn


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-26 14:15                     ` Björn Lundin
@ 2014-09-26 14:49                       ` J-P. Rosen
  2014-09-26 15:31                         ` Björn Lundin
  2014-09-26 16:43                       ` Niklas Holsti
  1 sibling, 1 reply; 30+ messages in thread
From: J-P. Rosen @ 2014-09-26 14:49 UTC (permalink / raw)


Le 26/09/2014 16:15, Björn Lundin a écrit :
> http://www.sigada.org/conf/sa98/papers/mueller.pdf
> 
> I did not read all of it, but the conclusion is that
> context switches are bad for performance.
> If a protected object can REPLACE a task, it
> will show in measurements. (and they did measure)

That's a paper from 16 years ago. Computers as well as compilers have
evolved a lot, therefore I would not trust the paper for making a
decision nowadays...

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-26 14:49                       ` J-P. Rosen
@ 2014-09-26 15:31                         ` Björn Lundin
  2014-09-26 16:08                           ` G.B.
                                             ` (2 more replies)
  0 siblings, 3 replies; 30+ messages in thread
From: Björn Lundin @ 2014-09-26 15:31 UTC (permalink / raw)


On 2014-09-26 16:49, J-P. Rosen wrote:
> Le 26/09/2014 16:15, Björn Lundin a écrit :
>> http://www.sigada.org/conf/sa98/papers/mueller.pdf
>>
>> I did not read all of it, but the conclusion is that
>> context switches are bad for performance.
>> If a protected object can REPLACE a task, it
>> will show in measurements. (and they did measure)
> 
> That's a paper from 16 years ago. Computers as well as compilers have
> evolved a lot, therefore I would not trust the paper for making a
> decision nowadays...
> 

Yes, I did point that out.
But still, I have no problem believing
that context switches still is bad for performance.

In the OP's example, I do not think it matters,
but there may be other situations where it does.

It's funny though that you want measurements,
and when you get them, you say they are too old.


--
Björn



^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-26 15:31                         ` Björn Lundin
@ 2014-09-26 16:08                           ` G.B.
  2014-09-30  4:22                             ` Brad Moore
  2014-09-26 16:23                           ` Dmitry A. Kazakov
  2014-09-26 20:38                           ` J-P. Rosen
  2 siblings, 1 reply; 30+ messages in thread
From: G.B. @ 2014-09-26 16:08 UTC (permalink / raw)


On 26.09.14 17:31, Björn Lundin wrote:
> On 2014-09-26 16:49, J-P. Rosen wrote:
>> Le 26/09/2014 16:15, Björn Lundin a écrit :
>>> http://www.sigada.org/conf/sa98/papers/mueller.pdf
>>>
>>> I did not read all of it, but the conclusion is that
>>> context switches are bad for performance.
>>> If a protected object can REPLACE a task, it
>>> will show in measurements. (and they did measure)
>>
>> That's a paper from 16 years ago. Computers as well as compilers have
>> evolved a lot, therefore I would not trust the paper for making a
>> decision nowadays...
>>
>
> Yes, I did point that out.
> But still, I have no problem believing
> that context switches still is bad for performance.

Task switches, or tasks in the first place, are,
apparently, heavy weight. That's by comparing two Ada programs,

http://benchmarksgame.alioth.debian.org/u64q/program.php?test=threadring&lang=gnat&id=2

to

http://benchmarksgame.alioth.debian.org/u64q/program.php?test=threadring&lang=gnat&id=4

and then both of them to the "different kind" of parallelism
exhibited by the leading entries. The leading entries are faster by
an orders of magnitude, even though the faster Ada program uses
just semaphores.

It might be better for Ada if at least the parallel loop initiatives
announced in Ada Letters are getting somewhere. I'm just guessing at
the effectiveness WRT async little things, though.



^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-26 15:31                         ` Björn Lundin
  2014-09-26 16:08                           ` G.B.
@ 2014-09-26 16:23                           ` Dmitry A. Kazakov
  2014-09-26 20:38                           ` J-P. Rosen
  2 siblings, 0 replies; 30+ messages in thread
From: Dmitry A. Kazakov @ 2014-09-26 16:23 UTC (permalink / raw)


On Fri, 26 Sep 2014 17:31:45 +0200, Björn Lundin wrote:

> On 2014-09-26 16:49, J-P. Rosen wrote:
>> Le 26/09/2014 16:15, Björn Lundin a écrit :
>>> http://www.sigada.org/conf/sa98/papers/mueller.pdf
>>>
>>> I did not read all of it, but the conclusion is that
>>> context switches are bad for performance.
>>> If a protected object can REPLACE a task, it
>>> will show in measurements. (and they did measure)
>> 
>> That's a paper from 16 years ago. Computers as well as compilers have
>> evolved a lot, therefore I would not trust the paper for making a
>> decision nowadays...
> 
> Yes, I did point that out.
> But still, I have no problem believing
> that context switches still is bad for performance.

Undoubtedly so. But on a multi-core architecture there might be no context
switch needed. In that case rendezvous might become as fast as a call to a
protected object's entry.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-26 14:15                     ` Björn Lundin
  2014-09-26 14:49                       ` J-P. Rosen
@ 2014-09-26 16:43                       ` Niklas Holsti
  1 sibling, 0 replies; 30+ messages in thread
From: Niklas Holsti @ 2014-09-26 16:43 UTC (permalink / raw)


On 14-09-26 17:15 , Björn Lundin wrote:

> And I now learned that render-vouz is spelled rendezvous

Ah yes... according to Wikipedia, rendez-vous is the French spelling,
rendezvous is the English one. So I should have used rendezvous. But I
was reading a French detective novel at the time...

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
      .      @       .


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-25 22:27           ` Jeffrey Carter
  2014-09-26  7:04             ` Björn Lundin
@ 2014-09-26 16:44             ` Niklas Holsti
  1 sibling, 0 replies; 30+ messages in thread
From: Niklas Holsti @ 2014-09-26 16:44 UTC (permalink / raw)


On 14-09-26 01:27 , Jeffrey Carter wrote:
> On 09/25/2014 01:10 PM, Niklas Holsti wrote:
>>
>> To make task-safe use of Ada.Text_IO, it should be wrapped in some way
>> to ensure that only one task calls it at a time. For example, you could
>> write a task with an entry like Put_Line (Message : in String) and an
>> accept statement that does Ada.Text_IO.Put_Line (Message). But a
>> protected-object wrapper is probably better for uses where I/O
>> performance (latency) is not critical.
> 
> Except that I/O is potentially blocking, and so cannot appear in a protected
> operation, meaning one needs a task one way or another.

Yes. Apologies for my error.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
      .      @       .


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-26  7:58               ` J-P. Rosen
  2014-09-26 10:24                 ` G.B.
  2014-09-26 11:48                 ` Björn Lundin
@ 2014-09-26 16:45                 ` Niklas Holsti
  2014-10-09  2:45                   ` Randy Brukardt
  2 siblings, 1 reply; 30+ messages in thread
From: Niklas Holsti @ 2014-09-26 16:45 UTC (permalink / raw)


On 14-09-26 10:58 , J-P. Rosen wrote:
> Le 26/09/2014 09:04, Björn Lundin a écrit :
>> Or by using a protected object as a semaphore
>>
> But why? It's so simpler with a task:
> 
>    task Printer is
>       entry Print (Mess : String);
>    end Printer;

The semaphore solution lets one group related output lines together; the
task+entry (in the above form) can interleave output lines from
different tasks, perhaps making output harder to read. Whether this
matters depends on what one needs.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
      .      @       .


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-26 15:31                         ` Björn Lundin
  2014-09-26 16:08                           ` G.B.
  2014-09-26 16:23                           ` Dmitry A. Kazakov
@ 2014-09-26 20:38                           ` J-P. Rosen
  2014-09-27 18:16                             ` Björn Lundin
  2 siblings, 1 reply; 30+ messages in thread
From: J-P. Rosen @ 2014-09-26 20:38 UTC (permalink / raw)


Le 26/09/2014 17:31, Björn Lundin a écrit :
> It's funny though that you want measurements,
> and when you get them, you say they are too old.

My first experience with efficiency issues is that, when you make
measurements, you are always surprised by the results; that's why I
always ask for measurements.

But then, measurements must be significant, i.e. as close as possible to
the context where they will be used. I was just saying that this one was
presumably too far away for the current context...

(just as an -unrelated- example: one of my programs doubled its speed
when AdaCore improved its implementation of unbounded strings...)

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-26 20:38                           ` J-P. Rosen
@ 2014-09-27 18:16                             ` Björn Lundin
  0 siblings, 0 replies; 30+ messages in thread
From: Björn Lundin @ 2014-09-27 18:16 UTC (permalink / raw)


On 2014-09-26 22:38, J-P. Rosen wrote:
> Le 26/09/2014 17:31, Björn Lundin a écrit :
>> It's funny though that you want measurements,
>> and when you get them, you say they are too old.

> 
> But then, measurements must be significant, i.e. as close as possible to
> the context where they will be used. I was just saying that this one was
> presumably too far away for the current context...
> 

Well, the spec for a pc around the year 2000 was
a single cpu - 1 core - with 256 mb ram. I still got a Dell c600
laptop from that time.

and incidentally, that is the spec of a raspberry pi - model b1, which I
do a fair bit of development in ada for.

So, the paper is not that far away for some of todays context.


-- 
--
Björn


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-26 16:08                           ` G.B.
@ 2014-09-30  4:22                             ` Brad Moore
  2014-09-30 21:59                               ` Georg Bauhaus
  0 siblings, 1 reply; 30+ messages in thread
From: Brad Moore @ 2014-09-30  4:22 UTC (permalink / raw)


On 14-09-26 10:08 AM, G.B. wrote:
> On 26.09.14 17:31, Björn Lundin wrote:
>> On 2014-09-26 16:49, J-P. Rosen wrote:
>>> Le 26/09/2014 16:15, Björn Lundin a écrit :
>>>> http://www.sigada.org/conf/sa98/papers/mueller.pdf
>>>>
>>>> I did not read all of it, but the conclusion is that
>>>> context switches are bad for performance.
>>>> If a protected object can REPLACE a task, it
>>>> will show in measurements. (and they did measure)
>>>
>>> That's a paper from 16 years ago. Computers as well as compilers have
>>> evolved a lot, therefore I would not trust the paper for making a
>>> decision nowadays...
>>>
>>
>> Yes, I did point that out.
>> But still, I have no problem believing
>> that context switches still is bad for performance.
>
> Task switches, or tasks in the first place, are,
> apparently, heavy weight. That's by comparing two Ada programs,
>
> http://benchmarksgame.alioth.debian.org/u64q/program.php?test=threadring&lang=gnat&id=2
>
>
> to
>
> http://benchmarksgame.alioth.debian.org/u64q/program.php?test=threadring&lang=gnat&id=4
>

Apparently the heaviness of tasks is dependent on usage.

I just submitted another version that was accepted today, which moves 
Ada up the ladder a bit.

http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=threadring

In fact, only the Go and the Haskell entries are consistently ahead of 
this latest version for all 4 processor configurations. The Ada version 
has 503 tasks executing with calls on a protected entry (where each task 
maps to an OS thread in GNAT). Looking at the Go example, I'm guessing 
that the 503 lightweight threads are being executed by a single OS 
thread, likely under a work-stealing scheduler, where the work never 
gets stolen by other cores, since this benchmark mostly involves a 
sequential handoff of a token to the next thread. It that's whats 
happening, then it might explain why the Go version is still quite a bit 
faster, since executing the problem on the same core doesn't require as 
much overhead and locking to do the handoff.


>
> and then both of them to the "different kind" of parallelism
> exhibited by the leading entries. The leading entries are faster by
> an orders of magnitude, even though the faster Ada program uses
> just semaphores.
>
> It might be better for Ada if at least the parallel loop initiatives
> announced in Ada Letters are getting somewhere. I'm just guessing at
> the effectiveness WRT async little things, though.
>


The proposals are gathering steam. We are moved the design of our 
proposal along quite a bit since the earlier papers, and even quite a 
bit since our most recent paper. In fact, our latest paper is being 
presented at HILT 2014 in Portland next month. The syntax has been 
revamped and simplified, while providing
better information to the compiler so that the compiler may verify if 
the parallelism can occur while also allowing the compiler to do more 
implicit parallelism.

Now seems a good opportunity to plug the conference.... :-)

Come to HILT everyone!  (High Integrity Language Technologies)
October 18-21, 2014 — Portland, Oregon (USA).

http://sigada.org/conf/hilt2014/

This year HILT is colocated with the SPLASH conference (Systems, 
Programming, Languages, and Applications: Software for Humanity)

http://2014.splashcon.org/

Brad


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-30  4:22                             ` Brad Moore
@ 2014-09-30 21:59                               ` Georg Bauhaus
  2014-10-01 15:38                                 ` Brad Moore
  0 siblings, 1 reply; 30+ messages in thread
From: Georg Bauhaus @ 2014-09-30 21:59 UTC (permalink / raw)


On 30.09.14 06:22, Brad Moore wrote:
> In fact, only the Go and the Haskell entries are consistently ahead of this latest version for all 4 processor configurations. The Ada version has 503 tasks executing with calls on a protected entry (where each task maps to an OS thread in GNAT). Looking at the Go example, I'm guessing that the 503 lightweight threads are being executed by a single OS thread, likely under a work-stealing scheduler, where the work never gets stolen by other cores, since this benchmark mostly involves a sequential handoff of a token to the next thread. It that's whats happening, then it might explain why the Go version is still quite a bit faster, since executing the problem on the same core doesn't require as much overhead and locking to do the handoff.
>
>

FWIW, adding (to #6)

  delay 0.0;

to the task body after the conditional loop exit resulted in some
changes in running time, on my testing machines. Results depend very
much on the compiler, and on (absence of) optimization.
Nothing like the order of magnitude of #6, though.

(On GNU/Linux: the system compiler (Debian, gcc 4.4.5) and GNAT 2013
4.7.4; Xeon E5-2620, two cores of a KVM.)



^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-30 21:59                               ` Georg Bauhaus
@ 2014-10-01 15:38                                 ` Brad Moore
  0 siblings, 0 replies; 30+ messages in thread
From: Brad Moore @ 2014-10-01 15:38 UTC (permalink / raw)


On 14-09-30 03:59 PM, Georg Bauhaus wrote:
> On 30.09.14 06:22, Brad Moore wrote:
>> In fact, only the Go and the Haskell entries are consistently ahead of
>> this latest version for all 4 processor configurations. The Ada
>> version has 503 tasks executing with calls on a protected entry (where
>> each task maps to an OS thread in GNAT). Looking at the Go example,
>> I'm guessing that the 503 lightweight threads are being executed by a
>> single OS thread, likely under a work-stealing scheduler, where the
>> work never gets stolen by other cores, since this benchmark mostly
>> involves a sequential handoff of a token to the next thread. It that's
>> whats happening, then it might explain why the Go version is still
>> quite a bit faster, since executing the problem on the same core
>> doesn't require as much overhead and locking to do the handoff.
>>
>>
>
> FWIW, adding (to #6)
>
>   delay 0.0;
>
> to the task body after the conditional loop exit resulted in some
> changes in running time, on my testing machines. Results depend very
> much on the compiler, and on (absence of) optimization.
> Nothing like the order of magnitude of #6, though.
>
> (On GNU/Linux: the system compiler (Debian, gcc 4.4.5) and GNAT 2013
> 4.7.4; Xeon E5-2620, two cores of a KVM.)
>


I tried your suggestion on my system. Ubuntu/Linux GPL 2014 compiler AMD 
quadcore, but this added 20-30 seconds to the processing time unfortunately.

Incidentally, I believe the reason approach #6 works is because the task 
executing a protected entry can execute the protected action on behalf 
of the other tasks that have passed the guard on that protected entry. 
(See RM 9.5.3 22-23)




^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: can someone help me with this code (explanation)
  2014-09-26 16:45                 ` Niklas Holsti
@ 2014-10-09  2:45                   ` Randy Brukardt
  0 siblings, 0 replies; 30+ messages in thread
From: Randy Brukardt @ 2014-10-09  2:45 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1222 bytes --]

"Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message 
news:c8ljhpFaqrfU4@mid.individual.net...
> On 14-09-26 10:58 , J-P. Rosen wrote:
>> Le 26/09/2014 09:04, Björn Lundin a écrit :
>>> Or by using a protected object as a semaphore
>>>
>> But why? It's so simpler with a task:
>>
>>    task Printer is
>>       entry Print (Mess : String);
>>    end Printer;
>
> The semaphore solution lets one group related output lines together; the
> task+entry (in the above form) can interleave output lines from
> different tasks, perhaps making output harder to read. Whether this
> matters depends on what one needs.

Right. Note that the semaphore ought to be wrapped in a Limited_Controlled 
object so that it gets unlocked if the scope is exited by an exception. 
That's especially important for protecting I/O, since I/O routines have a 
tendency to propagate an exception because of full disks, permissions 
errors, etc. Without such protection, an exception would leave the semaphore 
locked and you'll end up with deadlock as no task can do any I/O. (The task 
version probably ought to be protected from exceptions as well, I'll leave 
that as an exercise for the reader.)

                            Randy.


^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2014-10-09  2:45 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-25 13:44 can someone help me with this code (explanation) Stribor40
2014-09-25 14:56 ` Björn Lundin
2014-09-25 15:01   ` Björn Lundin
2014-09-25 15:54   ` Stribor40
2014-09-25 17:11     ` Niklas Holsti
2014-09-25 19:41       ` Stribor40
2014-09-25 19:53         ` Jeffrey Carter
2014-09-25 20:10         ` Niklas Holsti
2014-09-25 22:27           ` Jeffrey Carter
2014-09-26  7:04             ` Björn Lundin
2014-09-26  7:58               ` J-P. Rosen
2014-09-26 10:24                 ` G.B.
2014-09-26 11:48                 ` Björn Lundin
2014-09-26 12:49                   ` J-P. Rosen
2014-09-26 14:15                     ` Björn Lundin
2014-09-26 14:49                       ` J-P. Rosen
2014-09-26 15:31                         ` Björn Lundin
2014-09-26 16:08                           ` G.B.
2014-09-30  4:22                             ` Brad Moore
2014-09-30 21:59                               ` Georg Bauhaus
2014-10-01 15:38                                 ` Brad Moore
2014-09-26 16:23                           ` Dmitry A. Kazakov
2014-09-26 20:38                           ` J-P. Rosen
2014-09-27 18:16                             ` Björn Lundin
2014-09-26 16:43                       ` Niklas Holsti
2014-09-26 16:45                 ` Niklas Holsti
2014-10-09  2:45                   ` Randy Brukardt
2014-09-26 16:44             ` Niklas Holsti
2014-09-26  5:06           ` J-P. Rosen
2014-09-25 16:53 ` Jeffrey Carter

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