comp.lang.ada
 help / color / mirror / Atom feed
* Allocation question
@ 2009-05-11 10:23 Olivier Scalbert
  2009-05-11 10:38 ` Georg Bauhaus
                   ` (5 more replies)
  0 siblings, 6 replies; 30+ messages in thread
From: Olivier Scalbert @ 2009-05-11 10:23 UTC (permalink / raw)


Hello,

I have write a small package:

---------------------------------------------------
-- ads
---------------------------------------------------
package Image is

     type Color_T is record
         Red:   Integer;
         Green: Integer;
         Blue:  Integer;
     end record;

     type Image_T is array(Positive range <>, Positive range <>) of Color_T;

     procedure Fill(Image: in out Image_T; Color: Color_T);

end Image;

---------------------------------------------------
-- adb
---------------------------------------------------
package body Image is

procedure Fill(Image: in out Image_T; Color: Color_T) is
begin
      for x in Image'range(1) loop
          for y in Image'range(2) loop
              Image(x,y) := Color;
          end loop;
      end loop;
end Fill;

end Image;


---------------------------------------------------
-- test
---------------------------------------------------
with Image;
use Image;

procedure Test_Image is
     Image : Image_T(1..100, 1..100);
     FillColor : constant Color_T := (0, 0, 0);
begin
     Fill(Image, FillColor);
end Test_Image;


This program seems to work.
However when I increase the size of Image, I get a Segmentation fault.

Should I need to play with access type and allocation stuff ?

Thanks,

Olivier





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

* Re: Allocation question
  2009-05-11 10:23 Allocation question Olivier Scalbert
@ 2009-05-11 10:38 ` Georg Bauhaus
  2009-05-11 10:40 ` Ludovic Brenta
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 30+ messages in thread
From: Georg Bauhaus @ 2009-05-11 10:38 UTC (permalink / raw)


Olivier Scalbert schrieb:

> ---------------------------------------------------
> -- test
> ---------------------------------------------------
> with Image;
> use Image;
> 
> procedure Test_Image is
>     Image : Image_T(1..100, 1..100);
>     FillColor : constant Color_T := (0, 0, 0);
> begin
>     Fill(Image, FillColor);
> end Test_Image;
> 
> 
> This program seems to work.
> However when I increase the size of Image, I get a Segmentation fault.
> 
> Should I need to play with access type and allocation stuff ?

Access types won't be necessary, in principle.
Asssuming you are using GNAT with standard options,
suitable compiler switches might solve the problem.
(IIRC, it has to do with recent GCC policies that
assume small data structures on the stack for reasons
unrelated to Ada, and then stack checking.)

Be sure to turn on -gnato and -fstack-check when you
want to run GNAT in Ada mode.






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

* Re: Allocation question
  2009-05-11 10:23 Allocation question Olivier Scalbert
  2009-05-11 10:38 ` Georg Bauhaus
@ 2009-05-11 10:40 ` Ludovic Brenta
  2009-05-11 12:14   ` Olivier Scalbert
  2009-05-11 12:26   ` Jacob Sparre Andersen
  2009-05-11 10:51 ` Use aggregates (Was: Allocation question) Jacob Sparre Andersen
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 30+ messages in thread
From: Ludovic Brenta @ 2009-05-11 10:40 UTC (permalink / raw)


On May 11, 12:23 pm, Olivier Scalbert <olivier.scalb...@algosyn.com>
wrote:
> procedure Test_Image is
>      Image : Image_T(1..100, 1..100);
>      FillColor : constant Color_T := (0, 0, 0);
> begin
>      Fill(Image, FillColor);
> end Test_Image;
>
> This program seems to work.
> However when I increase the size of Image, I get a Segmentation fault.
>
> Should I need to play with access type and allocation stuff ?

Yes. Your image is on the stack. You can increase the size of the
stack up to an operating-system-dependent maximum (see ulimit(1) on
Unix-like systems) but there is always a limit. For potentially very
large objects, I think the better approach is to allocate them on the
heap. I would suggest you hide the allocation and deallocation inside
a controlled object which you declare on the stack, e.g.

private with Ada.Finalization;
package Image is
   type Image_T (Width, Height : Natural := 0) is private;
private
   type Data_T is array(Positive range <>, Positive range <>) of
Color_T;
   type Data_Access_T is access Data_T;
   type Image_T (Width, Height : Natural) is
     new Ada.Finalization.Controlled with record
      Data : Data_Access_T;
   end record;
   overriding procedure Initialize (Object : in out Image_T); --
allocates
   overriding procedure Adjust(Object : in out Image_T); -- duplicates
Data.all?
   overriding procedure Finalize(Object : in out Image_T); --
deallocates
end Image;

with Image;
declare
   Im1 : Image.Image_T (1 .. 1024, 1 .. 1024); -- calls Initialize
which allocates
   Im2 : Image.Image_T (0, 0); -- calls Initialize which does nothing
begin
   Im2 := Im1; -- calls Finalize (Im2) then Adjust (Im2)
end; -- calls Finalize for both

You may also share image data between objects.

For even larger objects you can make Initialize, Adjust and Finalize
much more sophisticated and store parts of the object on the heap and
part on disk. You would do that only if you think you can beat the
performance of your kernel's paging subsystem.

HTH

--
Ludovic Brenta.



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

* Use aggregates (Was: Allocation question)
  2009-05-11 10:23 Allocation question Olivier Scalbert
  2009-05-11 10:38 ` Georg Bauhaus
  2009-05-11 10:40 ` Ludovic Brenta
@ 2009-05-11 10:51 ` Jacob Sparre Andersen
  2009-05-11 11:46   ` Olivier Scalbert
                     ` (2 more replies)
  2009-05-11 10:57 ` Allocation question Philipp Riegger
                   ` (2 subsequent siblings)
  5 siblings, 3 replies; 30+ messages in thread
From: Jacob Sparre Andersen @ 2009-05-11 10:51 UTC (permalink / raw)


Olivier Scalbert wrote:

> procedure Fill(Image: in out Image_T; Color: Color_T) is
> begin
>       for x in Image'range(1) loop
>           for y in Image'range(2) loop
>               Image(x,y) := Color;
>           end loop;
>       end loop;
> end Fill;

I would sugges that you rather wrote this:

   Image := (others => (others => Color));

It is a more precise expression of what (I guess) you want done, and
thus it gives the compiler more precise information to work with.

Greetings,

Jacob
-- 
"Any newsgroup where software developers hang out is
 an Emacs newsgroup."



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

* Re: Allocation question
  2009-05-11 10:23 Allocation question Olivier Scalbert
                   ` (2 preceding siblings ...)
  2009-05-11 10:51 ` Use aggregates (Was: Allocation question) Jacob Sparre Andersen
@ 2009-05-11 10:57 ` Philipp Riegger
  2009-05-11 12:18   ` Georg Bauhaus
  2009-05-11 23:32 ` Brian Drummond
  2009-05-12  1:09 ` tmoran
  5 siblings, 1 reply; 30+ messages in thread
From: Philipp Riegger @ 2009-05-11 10:57 UTC (permalink / raw)


On Mon, 11 May 2009 12:23:11 +0200
Olivier Scalbert <olivier.scalbert@algosyn.com> wrote:

>      type Color_T is record
>          Red:   Integer;
>          Green: Integer;
>          Blue:  Integer;
>      end record;

You can force a Size of 2 bit for this type by "for Color_T'Size use
2;".

>      type Image_T is array(Positive range <>, Positive range <>) of
> Color_T;

"Pragma Pack (Image_T);" tells the compiler not to align the array to
words (4 byte, i guess) but to use the 2 bit for each Color_T. Slower, but decreases the stack usage.

Philipp



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

* Re: Use aggregates (Was: Allocation question)
  2009-05-11 10:51 ` Use aggregates (Was: Allocation question) Jacob Sparre Andersen
@ 2009-05-11 11:46   ` Olivier Scalbert
  2009-05-11 12:16   ` Ludovic Brenta
  2009-05-12  9:13   ` Emacs Stephen Leake
  2 siblings, 0 replies; 30+ messages in thread
From: Olivier Scalbert @ 2009-05-11 11:46 UTC (permalink / raw)


Jacob Sparre Andersen wrote:
> Olivier Scalbert wrote:
> 
>> procedure Fill(Image: in out Image_T; Color: Color_T) is
>> begin
>>       for x in Image'range(1) loop
>>           for y in Image'range(2) loop
>>               Image(x,y) := Color;
>>           end loop;
>>       end loop;
>> end Fill;
> 
> I would sugges that you rather wrote this:
> 
>    Image := (others => (others => Color));
> 
> It is a more precise expression of what (I guess) you want done, and
> thus it gives the compiler more precise information to work with.
> 
> Greetings,
> 
> Jacob
Yes you are right ! But I was so happy to use Image'range !
:-)



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

* Re: Allocation question
  2009-05-11 10:40 ` Ludovic Brenta
@ 2009-05-11 12:14   ` Olivier Scalbert
  2009-05-11 12:18     ` Ludovic Brenta
  2009-05-11 12:26   ` Jacob Sparre Andersen
  1 sibling, 1 reply; 30+ messages in thread
From: Olivier Scalbert @ 2009-05-11 12:14 UTC (permalink / raw)


Ludovic Brenta wrote:

> Yes. Your image is on the stack. You can increase the size of the
> stack up to an operating-system-dependent maximum (see ulimit(1) on
> Unix-like systems) but there is always a limit. For potentially very
> large objects, I think the better approach is to allocate them on the
> heap. I would suggest you hide the allocation and deallocation inside
> a controlled object which you declare on the stack, e.g.
> 
> private with Ada.Finalization;
> package Image is
>    type Image_T (Width, Height : Natural := 0) is private;
> private
>    type Data_T is array(Positive range <>, Positive range <>) of
> Color_T;
>    type Data_Access_T is access Data_T;
>    type Image_T (Width, Height : Natural) is
>      new Ada.Finalization.Controlled with record
>       Data : Data_Access_T;
>    end record;
>    overriding procedure Initialize (Object : in out Image_T); --
> allocates
>    overriding procedure Adjust(Object : in out Image_T); -- duplicates
> Data.all?
>    overriding procedure Finalize(Object : in out Image_T); --
> deallocates
> end Image;
> 
> with Image;
> declare
>    Im1 : Image.Image_T (1 .. 1024, 1 .. 1024); -- calls Initialize
> which allocates
>    Im2 : Image.Image_T (0, 0); -- calls Initialize which does nothing
> begin
>    Im2 := Im1; -- calls Finalize (Im2) then Adjust (Im2)
> end; -- calls Finalize for both
> 
> You may also share image data between objects.
> 
> For even larger objects you can make Initialize, Adjust and Finalize
> much more sophisticated and store parts of the object on the heap and
> part on disk. You would do that only if you think you can beat the
> performance of your kernel's paging subsystem.
> 
> HTH
> 
> --
> Ludovic Brenta.

Thanks Ludovic.

procedure Initialize (Object : in out Image_T) is
begin
     Ada.Text_IO.Put("Initialize");
     -- What shall I put here ?
end Initialize;


Olivier.



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

* Re: Use aggregates (Was: Allocation question)
  2009-05-11 10:51 ` Use aggregates (Was: Allocation question) Jacob Sparre Andersen
  2009-05-11 11:46   ` Olivier Scalbert
@ 2009-05-11 12:16   ` Ludovic Brenta
  2009-05-11 21:26     ` sjw
  2009-05-12  7:47     ` Use aggregates (Was: Allocation question) Martin
  2009-05-12  9:13   ` Emacs Stephen Leake
  2 siblings, 2 replies; 30+ messages in thread
From: Ludovic Brenta @ 2009-05-11 12:16 UTC (permalink / raw)


Jacob Sparre Andersen wrote on comp.lang.ada:
> Olivier Scalbert wrote:
> > procedure Fill(Image: in out Image_T; Color: Color_T) is
> > begin
> >       for x in Image'range(1) loop
> >           for y in Image'range(2) loop
> >               Image(x,y) := Color;
> >           end loop;
> >       end loop;
> > end Fill;
>
> I would sugges that you rather wrote this:
>
>    Image := (others => (others => Color));
>
> It is a more precise expression of what (I guess) you want done, and
> thus it gives the compiler more precise information to work with.

This is not always a good idea. On some targets, GNAT places the
aggregate on the stack and this can raise a Storage_Error. In avionics
programs, I remember replacing aggregates with loops for this reason.

--
Ludovic Brenta.



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

* Re: Allocation question
  2009-05-11 10:57 ` Allocation question Philipp Riegger
@ 2009-05-11 12:18   ` Georg Bauhaus
  2009-05-11 12:36     ` Philipp Riegger
  0 siblings, 1 reply; 30+ messages in thread
From: Georg Bauhaus @ 2009-05-11 12:18 UTC (permalink / raw)


Philipp Riegger schrieb:
> On Mon, 11 May 2009 12:23:11 +0200
> Olivier Scalbert <olivier.scalbert@algosyn.com> wrote:
> 
>>      type Color_T is record
>>          Red:   Integer;
>>          Green: Integer;
>>          Blue:  Integer;
>>      end record;
> 
> You can force a Size of 2 bit for this type by "for Color_T'Size use
> 2;".


How would this work? In fact,

==============Error messages for source file: image.ads

     9.     for Color_T'Size use 2;
                                 |
        >>> size for "Color_T" too small, minimum allowed is 96

    11.     type Image_T is array(Positive range <>, Positive range <>)
of Color_T;
                 |
        >>> component size for "Image_T" too small, minimum allowed is 96


But I'd add a type for the range of permissible values per color.
If each value is in range 0 .. 255, then three of them will need
24 bits and the components of an array can be packed.



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

* Re: Allocation question
  2009-05-11 12:14   ` Olivier Scalbert
@ 2009-05-11 12:18     ` Ludovic Brenta
  2009-05-11 13:01       ` Olivier Scalbert
  0 siblings, 1 reply; 30+ messages in thread
From: Ludovic Brenta @ 2009-05-11 12:18 UTC (permalink / raw)


Olivier Scalbert wrote on comp.lang.ada:
> Ludovic Brenta wrote:
> > Yes. Your image is on the stack. You can increase the size of the
> > stack up to an operating-system-dependent maximum (see ulimit(1) on
> > Unix-like systems) but there is always a limit. For potentially very
> > large objects, I think the better approach is to allocate them on the
> > heap. I would suggest you hide the allocation and deallocation inside
> > a controlled object which you declare on the stack, e.g.
>
> > private with Ada.Finalization;
> > package Image is
> >    type Image_T (Width, Height : Natural := 0) is private;
> > private
> >    type Data_T is array(Positive range <>, Positive range <>) of
> > Color_T;
> >    type Data_Access_T is access Data_T;
> >    type Image_T (Width, Height : Natural) is
> >      new Ada.Finalization.Controlled with record
> >       Data : Data_Access_T;
> >    end record;
> >    overriding procedure Initialize (Object : in out Image_T); --
> > allocates
> >    overriding procedure Adjust(Object : in out Image_T); -- duplicates
> > Data.all?
> >    overriding procedure Finalize(Object : in out Image_T); --
> > deallocates
> > end Image;
>
> > with Image;
> > declare
> >    Im1 : Image.Image_T (1 .. 1024, 1 .. 1024); -- calls Initialize
> > which allocates
> >    Im2 : Image.Image_T (0, 0); -- calls Initialize which does nothing
> > begin
> >    Im2 := Im1; -- calls Finalize (Im2) then Adjust (Im2)
> > end; -- calls Finalize for both
>
> > You may also share image data between objects.
>
> > For even larger objects you can make Initialize, Adjust and Finalize
> > much more sophisticated and store parts of the object on the heap and
> > part on disk. You would do that only if you think you can beat the
> > performance of your kernel's paging subsystem.
>
> > HTH
>
> > --
> > Ludovic Brenta.
>
> Thanks Ludovic.
>
> procedure Initialize (Object : in out Image_T) is
> begin
>      Ada.Text_IO.Put("Initialize");
>      -- What shall I put here ?
> end Initialize;
>
> Olivier.

Read the Object's Width and Height (the discriminants can be read like
any other component). Allocate the Data_Array_T on the heap with the
corresponding size. Assign the result to Object.Data.

--
Ludovic Brenta.



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

* Re: Allocation question
  2009-05-11 10:40 ` Ludovic Brenta
  2009-05-11 12:14   ` Olivier Scalbert
@ 2009-05-11 12:26   ` Jacob Sparre Andersen
  2009-05-11 13:27     ` Ludovic Brenta
  1 sibling, 1 reply; 30+ messages in thread
From: Jacob Sparre Andersen @ 2009-05-11 12:26 UTC (permalink / raw)


Ludovic Brenta wrote:

> Yes. Your image is on the stack. You can increase the size of the
> stack up to an operating-system-dependent maximum (see ulimit(1) on
> Unix-like systems) but there is always a limit. For potentially very
> large objects, I think the better approach is to allocate them on
> the heap. I would suggest you hide the allocation and deallocation
> inside a controlled object which you declare on the stack, e.g.

Is there something which prevents an Ada compiler from allocating
large, local objects on the heap rather than on the stack?

Would it be very complicated to introduce a rule in a compiler (not in
the language), which makes local objects larger than some limit be
allocated on the stack?

> For even larger objects you can make Initialize, Adjust and Finalize
> much more sophisticated and store parts of the object on the heap
> and part on disk. You would do that only if you think you can beat
> the performance of your kernel's paging subsystem.

But then you would also make careful experiments to check if your
thinking was actually correct.

Greetings,

Jacob
-- 
A: Yes.
>Q: Are you sure?
>>A: Because it reverses the logical flow of conversation.
>>>Q: Why is top posting frowned upon?



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

* Re: Allocation question
  2009-05-11 12:18   ` Georg Bauhaus
@ 2009-05-11 12:36     ` Philipp Riegger
  0 siblings, 0 replies; 30+ messages in thread
From: Philipp Riegger @ 2009-05-11 12:36 UTC (permalink / raw)


On Mon, 11 May 2009 14:18:09 +0200
Georg Bauhaus <rm.dash-bauhaus@futureapps.de> wrote:

> How would this work?

You're right, I read the example too fast and thought, it was an
enumeration type with 3 entries. Thanks for the correction.

Phlipp



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

* Re: Allocation question
  2009-05-11 12:18     ` Ludovic Brenta
@ 2009-05-11 13:01       ` Olivier Scalbert
  0 siblings, 0 replies; 30+ messages in thread
From: Olivier Scalbert @ 2009-05-11 13:01 UTC (permalink / raw)


Ludovic Brenta wrote:

> 
> Read the Object's Width and Height (the discriminants can be read like
> any other component). Allocate the Data_Array_T on the heap with the
> corresponding size. Assign the result to Object.Data.
> 
> --
> Ludovic Brenta.

Ok. In fact I use gnat-gps. And the smart-completion feature does not 
propose Object.Width or Object.Height.

Olivier.



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

* Re: Allocation question
  2009-05-11 12:26   ` Jacob Sparre Andersen
@ 2009-05-11 13:27     ` Ludovic Brenta
  0 siblings, 0 replies; 30+ messages in thread
From: Ludovic Brenta @ 2009-05-11 13:27 UTC (permalink / raw)


Jacob Sparre Andersen wrote on comp.lang.ada:
> Is there something which prevents an Ada compiler from allocating
> large, local objects on the heap rather than on the stack?
>
> Would it be very complicated to introduce a rule in a compiler (not in
> the language), which makes local objects larger than some limit be
> allocated on the stack?

An interesting thought. I just re-read 3.11 and it only says that
declarative_parts are "elaborated". 3.3.1(18/2) is similarly terse on
object_declarations, saying only that "the object is created". The RM
doesn't seem to have a concept of a stack at all; this is left to the
implementation. So, I suppose you are correct that a compiler can
choose to allocate everything on the heap. In fact, I suspect that
that's what compilers targetting the Java virtual machine have to do.

For other targets, I guess it would make sense for some compilers to
introduce a pragma allowing the programmer to specify where the object
should be. For heap-allocated objects, I don't think it would be
overly difficult to replace an object_declaration with a synthetic
controlled object that encapsulates it in the manner I described
earlier.

--
Ludovic Brenta.



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

* Re: Use aggregates (Was: Allocation question)
  2009-05-11 12:16   ` Ludovic Brenta
@ 2009-05-11 21:26     ` sjw
  2009-05-12  5:58       ` GNAT, aggregates and efficiency (Was: Use aggregates) Jacob Sparre Andersen
  2009-05-12  7:47     ` Use aggregates (Was: Allocation question) Martin
  1 sibling, 1 reply; 30+ messages in thread
From: sjw @ 2009-05-11 21:26 UTC (permalink / raw)


On May 11, 1:16 pm, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote:
> Jacob Sparre Andersen wrote on comp.lang.ada:
>
>
>
> > Olivier Scalbert wrote:
> > > procedure Fill(Image: in out Image_T; Color: Color_T) is
> > > begin
> > >       for x in Image'range(1) loop
> > >           for y in Image'range(2) loop
> > >               Image(x,y) := Color;
> > >           end loop;
> > >       end loop;
> > > end Fill;
>
> > I would sugges that you rather wrote this:
>
> >    Image := (others => (others => Color));
>
> > It is a more precise expression of what (I guess) you want done, and
> > thus it gives the compiler more precise information to work with.
>
> This is not always a good idea. On some targets, GNAT places the
> aggregate on the stack and this can raise a Storage_Error. In avionics
> programs, I remember replacing aggregates with loops for this reason.

Someone recently found it was quicker to test an array for some
condition by looping through it rather than by comparing with an
aggregate [eg X = (others => 0)]. I had naively assumed that GNAT
would just do the comparisons of the elements of X against 0, as the
hand-crafted loop does, rather than construct a whole array of zeros
on the stack and then loop through that ...



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

* Re: Allocation question
  2009-05-11 10:23 Allocation question Olivier Scalbert
                   ` (3 preceding siblings ...)
  2009-05-11 10:57 ` Allocation question Philipp Riegger
@ 2009-05-11 23:32 ` Brian Drummond
  2009-05-12  1:09 ` tmoran
  5 siblings, 0 replies; 30+ messages in thread
From: Brian Drummond @ 2009-05-11 23:32 UTC (permalink / raw)


On Mon, 11 May 2009 12:23:11 +0200, Olivier Scalbert
<olivier.scalbert@algosyn.com> wrote:

>Hello,
>
>I have write a small package:
>
>---------------------------------------------------
>-- ads
>---------------------------------------------------
>package Image is
...
>with Image;
>use Image;
>
>procedure Test_Image is
>     Image : Image_T(1..100, 1..100);
>     FillColor : constant Color_T := (0, 0, 0);
>begin
>     Fill(Image, FillColor);
>end Test_Image;
>
>
>This program seems to work.
>However when I increase the size of Image, I get a Segmentation fault.
>
>Should I need to play with access type and allocation stuff ?

One simple approach is to use an access type for allocation, but use renaming to
maintain compatibility with what you've already written.

procedure Test_Image is
     Image_a   : access Image_t := new Image_T(1..1024, 1..1024);
     Image     : Image_t renames Image_a.all;
     FillColor : constant Color_T := (0, 0, 0);
begin
     Fill(Image, FillColor);
end Test_Image;

I am not in front of an Ada compiler right now so the syntax may be slightly
off, but I hope the basic idea is clear

- Brian



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

* Re: Allocation question
  2009-05-11 10:23 Allocation question Olivier Scalbert
                   ` (4 preceding siblings ...)
  2009-05-11 23:32 ` Brian Drummond
@ 2009-05-12  1:09 ` tmoran
  5 siblings, 0 replies; 30+ messages in thread
From: tmoran @ 2009-05-12  1:09 UTC (permalink / raw)


>      Image : Image_T(1..100, 1..100);
> ...
> This program seems to work.
> However when I increase the size of Image, I get a Segmentation fault.
>
> Should I need to play with access type and allocation stuff ?
   Using Janus Ada 95 on a 2GB W2k system, I can run with

     Image : Image_T(1..10_000, 1..10_000);

by putting a size option on the link command.  That's 1.2 GB and I do
need to leave some room for Windows etc.  It also takes a noticeable
time to run.
  What about Gnat for 64 bit Windows with large RAM?  Also, IIRC you
can make a separate task and use 'Storage_Size and get a large stack
that way.



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

* GNAT, aggregates and efficiency (Was: Use aggregates)
  2009-05-11 21:26     ` sjw
@ 2009-05-12  5:58       ` Jacob Sparre Andersen
  2009-05-12 18:57         ` sjw
  0 siblings, 1 reply; 30+ messages in thread
From: Jacob Sparre Andersen @ 2009-05-12  5:58 UTC (permalink / raw)


<simon.j.wright@mac.com> wrote:

> Someone recently found it was quicker to test an array for some
> condition by looping through it rather than by comparing with an
> aggregate [eg X = (others => 0)]. I had naively assumed that GNAT
> would just do the comparisons of the elements of X against 0, as the
> hand-crafted loop does, rather than construct a whole array of zeros
> on the stack and then loop through that ...

With which command line arguments and aggregate sizes is this the
case?

Greetings,

Jacob

PS: Never make premature local optimization!
-- 
"If I have to choose between two evils, I choose the one I
 haven't tried before."



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

* Re: Use aggregates (Was: Allocation question)
  2009-05-11 12:16   ` Ludovic Brenta
  2009-05-11 21:26     ` sjw
@ 2009-05-12  7:47     ` Martin
  2009-05-12 10:24       ` Brian Drummond
  2009-05-12 21:18       ` Randy Brukardt
  1 sibling, 2 replies; 30+ messages in thread
From: Martin @ 2009-05-12  7:47 UTC (permalink / raw)


On May 11, 1:16 pm, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote:
> Jacob Sparre Andersen wrote on comp.lang.ada:
>
>
>
> > Olivier Scalbert wrote:
> > > procedure Fill(Image: in out Image_T; Color: Color_T) is
> > > begin
> > >       for x in Image'range(1) loop
> > >           for y in Image'range(2) loop
> > >               Image(x,y) := Color;
> > >           end loop;
> > >       end loop;
> > > end Fill;
>
> > I would sugges that you rather wrote this:
>
> >    Image := (others => (others => Color));
>
> > It is a more precise expression of what (I guess) you want done, and
> > thus it gives the compiler more precise information to work with.
>
> This is not always a good idea. On some targets, GNAT places the
> aggregate on the stack and this can raise a Storage_Error. In avionics
> programs, I remember replacing aggregates with loops for this reason.
>
> --
> Ludovic Brenta.

And not just GNAT...in fact, I'm struggling to remember a compiler
that _doesn't_ do the "large and slow (and stupid?)" aggregate for
assignment (or initialisation).

If paying customers complained compiler vendors might do something to
generate more efficient code. Sadly, sometimes the response we got
[naming no particular company] was "It meets the RM, we're not doing
anything".

Cheers
-- Martin



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

* Re: Emacs
  2009-05-11 10:51 ` Use aggregates (Was: Allocation question) Jacob Sparre Andersen
  2009-05-11 11:46   ` Olivier Scalbert
  2009-05-11 12:16   ` Ludovic Brenta
@ 2009-05-12  9:13   ` Stephen Leake
  2009-05-12  9:38     ` Emacs Ludovic Brenta
  2009-05-12  9:46     ` Emacs Olivier Scalbert
  2 siblings, 2 replies; 30+ messages in thread
From: Stephen Leake @ 2009-05-12  9:13 UTC (permalink / raw)


Jacob Sparre Andersen <sparre@nbi.dk> writes:

> "Any newsgroup where software developers hang out is
>  an Emacs newsgroup."

This used to be much more true than it is now, unfortunately. I keep
running into people at work who "just use GEdit". Sigh.

-- 
-- Stephe



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

* Re: Emacs
  2009-05-12  9:13   ` Emacs Stephen Leake
@ 2009-05-12  9:38     ` Ludovic Brenta
  2009-05-12  9:46     ` Emacs Olivier Scalbert
  1 sibling, 0 replies; 30+ messages in thread
From: Ludovic Brenta @ 2009-05-12  9:38 UTC (permalink / raw)


Stephen Leake wrote on comp.lang.ada:
> Jacob Sparre Andersen <spa...@nbi.dk> writes:
>
> > "Any newsgroup where software developers hang out is
> >  an Emacs newsgroup."
>
> This used to be much more true than it is now, unfortunately. I keep
> running into people at work who "just use GEdit". Sigh.

I've been using Emacs as my main IDE both at home and at work since
2000, adding email and other things a couple of years later, and have
no plans of changing. One day I might even become a member of the
Church of Emacs :)

--
Ludovic Brenta.



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

* Re: Emacs
  2009-05-12  9:13   ` Emacs Stephen Leake
  2009-05-12  9:38     ` Emacs Ludovic Brenta
@ 2009-05-12  9:46     ` Olivier Scalbert
  1 sibling, 0 replies; 30+ messages in thread
From: Olivier Scalbert @ 2009-05-12  9:46 UTC (permalink / raw)


Stephen Leake wrote:
> Jacob Sparre Andersen <sparre@nbi.dk> writes:
> 
>> "Any newsgroup where software developers hang out is
>>  an Emacs newsgroup."
> 
> This used to be much more true than it is now, unfortunately. I keep
> running into people at work who "just use GEdit". Sigh.
> 

<troll>
     and what about vi/gvim ?
</troll>

;-)



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

* Re: Use aggregates (Was: Allocation question)
  2009-05-12  7:47     ` Use aggregates (Was: Allocation question) Martin
@ 2009-05-12 10:24       ` Brian Drummond
  2009-05-12 11:07         ` Georg Bauhaus
  2009-05-12 21:18       ` Randy Brukardt
  1 sibling, 1 reply; 30+ messages in thread
From: Brian Drummond @ 2009-05-12 10:24 UTC (permalink / raw)


On Tue, 12 May 2009 00:47:56 -0700 (PDT), Martin <martin.dowie@btopenworld.com>
wrote:

>On May 11, 1:16�pm, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote:
>> Jacob Sparre Andersen wrote on comp.lang.ada:
>>
>>
>>
>> > Olivier Scalbert wrote:
>> > > procedure Fill(Image: in out Image_T; Color: Color_T) is
>> > > begin
>> > > � � � for x in Image'range(1) loop
>> > > � � � � � for y in Image'range(2) loop
...

>> > I would sugges that you rather wrote this:
>>
>> > � �Image := (others => (others => Color));
>>
>> > It is a more precise expression of what (I guess) you want done, and
>> > thus it gives the compiler more precise information to work with.
>>
>> This is not always a good idea. On some targets, GNAT places the
>> aggregate on the stack and this can raise a Storage_Error. In avionics
>> programs, I remember replacing aggregates with loops for this reason.

>> Ludovic Brenta.

>If paying customers complained compiler vendors might do something to
>generate more efficient code. Sadly, sometimes the response we got
>[naming no particular company] was "It meets the RM, we're not doing
>anything".

If anything gives Ada the reputation for inefficiency and bloat, it's that sort
of missed opportunity, and not the language itself.

There is no fundamental reason why the compiler can't do as good a job as I can
at unrolling that into loops. And unfortunately, you have thrown away half the
point of using Ada, if you have to write C in Ada to match the performance of C.

- Brian




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

* Re: Use aggregates (Was: Allocation question)
  2009-05-12 10:24       ` Brian Drummond
@ 2009-05-12 11:07         ` Georg Bauhaus
  2009-05-12 11:14           ` Georg Bauhaus
  0 siblings, 1 reply; 30+ messages in thread
From: Georg Bauhaus @ 2009-05-12 11:07 UTC (permalink / raw)


Brian Drummond schrieb:

> If anything gives Ada the reputation for inefficiency and bloat, it's that sort
> of missed opportunity, and not the language itself.

(Did you try this with C99's variable length arrays?)

> There is no fundamental reason why the compiler can't do as good a job as I can
> at unrolling that into loops. And unfortunately, you have thrown away half the
> point of using Ada, if you have to write C in Ada to match the performance of C.

GNAT does seem to emit loop instructions for the following
input.  I get a REPZ in the assembly listing.  What do you get?

package A is

   pragma Pure;

   subtype Intensity is Natural range 0 .. 255;
   type Index is range 1 .. 100;
   type List is array(Index) of Intensity;

   Zero: constant List := List'(others => 0);

   function Is_Zero(Item: List) return Boolean;

end A;

package body A is

   function Is_Zero(Item: List) return Boolean is
   begin
      return Item = Zero;
   end Is_Zero;

end A;



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

* Re: Use aggregates (Was: Allocation question)
  2009-05-12 11:07         ` Georg Bauhaus
@ 2009-05-12 11:14           ` Georg Bauhaus
  0 siblings, 0 replies; 30+ messages in thread
From: Georg Bauhaus @ 2009-05-12 11:14 UTC (permalink / raw)


Georg Bauhaus schrieb:
> Brian Drummond schrieb:
> 
>> If anything gives Ada the reputation for inefficiency and bloat, it's that sort
>> of missed opportunity, and not the language itself.
> 
> (Did you try this with C99's variable length arrays?)
> 
>> There is no fundamental reason why the compiler can't do as good a job as I can
>> at unrolling that into loops. And unfortunately, you have thrown away half the
>> point of using Ada, if you have to write C in Ada to match the performance of C.
> 
> GNAT does seem to emit loop instructions for the following
> input.  I get a REPZ in the assembly listing. 

Which is beside the point. Please forget this.



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

* Re: GNAT, aggregates and efficiency (Was: Use aggregates)
  2009-05-12  5:58       ` GNAT, aggregates and efficiency (Was: Use aggregates) Jacob Sparre Andersen
@ 2009-05-12 18:57         ` sjw
  0 siblings, 0 replies; 30+ messages in thread
From: sjw @ 2009-05-12 18:57 UTC (permalink / raw)


On May 12, 6:58 am, Jacob Sparre Andersen <spa...@nbi.dk> wrote:
> <simon.j.wri...@mac.com> wrote:
> > Someone recently found it was quicker to test an array for some
> > condition by looping through it rather than by comparing with an
> > aggregate [eg X = (others => 0)]. I had naively assumed that GNAT
> > would just do the comparisons of the elements of X against 0, as the
> > hand-crafted loop does, rather than construct a whole array of zeros
> > on the stack and then loop through that ...
>
> With which command line arguments and aggregate sizes is this the
> case?

It was in this thread, I think:
http://groups.google.com/group/comp.lang.ada/browse_frm/thread/3737542e2ed2b8e1/faecd7f658a4da62?lnk=gst&q=adarubik#faecd7f658a4da62



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

* Re: Use aggregates (Was: Allocation question)
  2009-05-12  7:47     ` Use aggregates (Was: Allocation question) Martin
  2009-05-12 10:24       ` Brian Drummond
@ 2009-05-12 21:18       ` Randy Brukardt
  2009-05-13 16:38         ` Martin
  1 sibling, 1 reply; 30+ messages in thread
From: Randy Brukardt @ 2009-05-12 21:18 UTC (permalink / raw)


"Martin" <martin.dowie@btopenworld.com> wrote in message 
news:26af755b-0b90-429f-a688-86bf307da2b5@o20g2000vbh.googlegroups.com...
>> This is not always a good idea. On some targets, GNAT places the
>> aggregate on the stack and this can raise a Storage_Error. In avionics
>> programs, I remember replacing aggregates with loops for this reason.
>
>And not just GNAT...in fact, I'm struggling to remember a compiler
>that _doesn't_ do the "large and slow (and stupid?)" aggregate for
>assignment (or initialisation).

You must have not used many Ada compilers. I known that I personally wrote 
some 6000 lines of code to handle avoiding aggregate temporaries in 
Janus/Ada, and that was done after noting that most of the other Ada 
compilers that we tried did a much better job of it. Indeed, I've very 
dubious that GNAT does not do it in most cases.

But it is important to realize that Ada's rules about what does and does not 
get modified in an assignment can prevent such an optimization. The reason I 
had to write so much code was to detect all of the cases where the 
optimization cannot be done safely (safely in an Ada sense; the original 
programmer probably wouldn't care about the different), such as assigning 
different parts of the target object, certain exception cases, and the like.

Truely simple cases, such as (others => 0) when the constraint is static 
surely always should get done, but there are a lot of cases in the grey 
areas.

In any case, Ada compiler vendors don't make their compilers worse than 
necessary for no reason. There are a lot of things that can prevent 
optimizations, they're not because the vendor is "lazy". You could optimize 
without any of the rules Ada has, but the resulting program would not have 
very predictable results. That's a big deal for safety-critical uses, and 
(for me at least) important so that I can use optimization and no worry 
about whether it is going to change the behavior of the program in an 
important way.

                         Randy.





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

* Re: Use aggregates (Was: Allocation question)
  2009-05-12 21:18       ` Randy Brukardt
@ 2009-05-13 16:38         ` Martin
  2009-05-13 20:38           ` Randy Brukardt
  0 siblings, 1 reply; 30+ messages in thread
From: Martin @ 2009-05-13 16:38 UTC (permalink / raw)


On May 12, 10:18 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
> "Martin" <martin.do...@btopenworld.com> wrote in message
>
> news:26af755b-0b90-429f-a688-86bf307da2b5@o20g2000vbh.googlegroups.com...
>
> >> This is not always a good idea. On some targets, GNAT places the
> >> aggregate on the stack and this can raise a Storage_Error. In avionics
> >> programs, I remember replacing aggregates with loops for this reason.
>
> >And not just GNAT...in fact, I'm struggling to remember a compiler
> >that _doesn't_ do the "large and slow (and stupid?)" aggregate for
> >assignment (or initialisation).
>
> You must have not used many Ada compilers.

The current count is 7 (for my day job) + 3 (for home work).

Cheers
-- Martin



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

* Re: Use aggregates (Was: Allocation question)
  2009-05-13 16:38         ` Martin
@ 2009-05-13 20:38           ` Randy Brukardt
  2009-05-14 10:48             ` Martin
  0 siblings, 1 reply; 30+ messages in thread
From: Randy Brukardt @ 2009-05-13 20:38 UTC (permalink / raw)


>"Martin" <martin.dowie@btopenworld.com> wrote in message 
>news:7b4408e9-386d-471b-aad5-9d26dde12682@v17g2000vbb.googlegroups.com...
>On May 12, 10:18 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
>> "Martin" <martin.do...@btopenworld.com> wrote in message
>>
>> news:26af755b-0b90-429f-a688-86bf307da2b5@o20g2000vbh.googlegroups.com...
>>
>> >> This is not always a good idea. On some targets, GNAT places the
>> >> aggregate on the stack and this can raise a Storage_Error. In avionics
>> >> programs, I remember replacing aggregates with loops for this reason.
>>
>> >And not just GNAT...in fact, I'm struggling to remember a compiler
>> >that _doesn't_ do the "large and slow (and stupid?)" aggregate for
>> >assignment (or initialisation).
>>
>> You must have not used many Ada compilers.
>
>The current count is 7 (for my day job) + 3 (for home work).

Fascinating. I'd be interested in seeing an example where you are seeing 
compilers that are doing "large and slow" aggregate initialization or 
assignment, because I have to think we are talking about different things.

                         Randy.





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

* Re: Use aggregates (Was: Allocation question)
  2009-05-13 20:38           ` Randy Brukardt
@ 2009-05-14 10:48             ` Martin
  0 siblings, 0 replies; 30+ messages in thread
From: Martin @ 2009-05-14 10:48 UTC (permalink / raw)


On May 13, 9:38 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
> >"Martin" <martin.do...@btopenworld.com> wrote in message
> >news:7b4408e9-386d-471b-aad5-9d26dde12682@v17g2000vbb.googlegroups.com...
> >On May 12, 10:18 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
> >> "Martin" <martin.do...@btopenworld.com> wrote in message
>
> >>news:26af755b-0b90-429f-a688-86bf307da2b5@o20g2000vbh.googlegroups.com...
>
> >> >> This is not always a good idea. On some targets, GNAT places the
> >> >> aggregate on the stack and this can raise a Storage_Error. In avionics
> >> >> programs, I remember replacing aggregates with loops for this reason.
>
> >> >And not just GNAT...in fact, I'm struggling to remember a compiler
> >> >that _doesn't_ do the "large and slow (and stupid?)" aggregate for
> >> >assignment (or initialisation).
>
> >> You must have not used many Ada compilers.
>
> >The current count is 7 (for my day job) + 3 (for home work).
>
> Fascinating. I'd be interested in seeing an example where you are seeing
> compilers that are doing "large and slow" aggregate initialization or
> assignment, because I have to think we are talking about different things.
>
>                          Randy.

This is going back into the memory banks a bit but here goes...

Situations like:

package P is
   type R is record
      I : Integer;
      F : Float;
      B : Boolean;
   end record;
   type Index is range 1 .. 100;
   type A_Of_R is array (Index) of R;
   D : A_Of_R;
end P;

package P is
   ...
begin
   D := (others => (I => 100, F => 1.0, B => False));
end A;

Quite possibly 'R' has, on some projects, had a discriminant. On
others, it may have been an array of an array. On others again, 'R'
may have been 'private' and a 'Null_R' private constant exported and
used to initialise 'Data' in some other compilation unit.

Also, to be fair, the last time I came across this in production code
was a few years ago. I'm certainly not claiming that I've found every
Ada compiler I've ever used has down something 'slow'...I almost
certainly haven't had this sort of construct in every project I've
work on. I've only noticed it a small number of times when it became a
problem for our timing requirements.

But it was rather off-putting to be told 'it meets the RM - tough!.

Cheers
-- Martin



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

end of thread, other threads:[~2009-05-14 10:48 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-11 10:23 Allocation question Olivier Scalbert
2009-05-11 10:38 ` Georg Bauhaus
2009-05-11 10:40 ` Ludovic Brenta
2009-05-11 12:14   ` Olivier Scalbert
2009-05-11 12:18     ` Ludovic Brenta
2009-05-11 13:01       ` Olivier Scalbert
2009-05-11 12:26   ` Jacob Sparre Andersen
2009-05-11 13:27     ` Ludovic Brenta
2009-05-11 10:51 ` Use aggregates (Was: Allocation question) Jacob Sparre Andersen
2009-05-11 11:46   ` Olivier Scalbert
2009-05-11 12:16   ` Ludovic Brenta
2009-05-11 21:26     ` sjw
2009-05-12  5:58       ` GNAT, aggregates and efficiency (Was: Use aggregates) Jacob Sparre Andersen
2009-05-12 18:57         ` sjw
2009-05-12  7:47     ` Use aggregates (Was: Allocation question) Martin
2009-05-12 10:24       ` Brian Drummond
2009-05-12 11:07         ` Georg Bauhaus
2009-05-12 11:14           ` Georg Bauhaus
2009-05-12 21:18       ` Randy Brukardt
2009-05-13 16:38         ` Martin
2009-05-13 20:38           ` Randy Brukardt
2009-05-14 10:48             ` Martin
2009-05-12  9:13   ` Emacs Stephen Leake
2009-05-12  9:38     ` Emacs Ludovic Brenta
2009-05-12  9:46     ` Emacs Olivier Scalbert
2009-05-11 10:57 ` Allocation question Philipp Riegger
2009-05-11 12:18   ` Georg Bauhaus
2009-05-11 12:36     ` Philipp Riegger
2009-05-11 23:32 ` Brian Drummond
2009-05-12  1:09 ` tmoran

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