Re: [fpc-devel] Aligned dynamic arrays

2019-03-28 Thread Anthony Walter
Here is the full implementation of aligned arrays, let me know if it works
for you.

https://www.getlazarus.org/arrays/

Here is another example:

uses
  AlignArrays;

procedure Test;
var
  VertexData: TAlignedArray;
  V: PVec3;
  I: Integer;
begin
  VertexData.Length := 100; // page sized and aligned memory allocated here
  V := VertexData[0]; // get a reference to the first item
  for I := 0 to V.Length - 1 do
  begin
V^ := ComputeVertex(I); // write to vertex data faster via a pointer
Inc(V);
  end;
  for V in VertexData do // array like enumerators are supported
PrintVertex(V);
  V.Item[6] := ComputeVertex(Random(100)); // you can write directly using
this syntax
  V[7]^ := ComputeVertex(Random(100)); // or write by dereferencing  the
default indexer
end; // there is no need to free the memory, it is taken care of for you by
finalize
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Aligned dynamic arrays

2019-03-28 Thread J. Gareth Moreton
 Just to add a minor thing... while usually you don't have to align memory
any more coarsely than 16 bytes for XMM, 32 bytes for YMM and 64 bytes for
ZMM, the 4 kB granularity is useful for paging, especially if you're
reading or writing to a swap file.  An entire library of functions for
such memory management and alignment would definitely be beneficial. 
Using FastMM4 if at all possible is even better.
 And that record definition is pretty nice, I have to say!
 Gareth aka. Kit

 On Thu 28/03/19 22:40 , Anthony Walter sys...@gmail.com sent:
 Here is a brief follow up. I am working on other projects at the moment,
but I am confident this a simple solution. Please tell me if this somehow
will not fit you needs.
 Create a new type that is compatible with Array where Array = type array
of T.Define implcit conversions between the to types and similar
methodsCreate a Push and Pop methods, well as a read write Length property
and two indexers. Indexer named Reference is default and provides a memory
reference to TnIndexer named Item is available and provides a copy of Tn

 So we would have ...
   TAlignedArray = record
     type TReference = ^T;    type TValue = T;    FPage: Pointer; 
  FLength: Integer;    procedure SetLength(Value: Integer);   
function GetReference(Index: Integer): TReference;     function
GetItem(Index: Integer): TValue;    procedure SetItem(Index: Integer;
const Value: TValue);  public    procedure Push(const Item: TValue); 
  procedure Pop: TValue;    property Length: Integer read FLength write
SetLength;    property Reference[Index: Integer]: TValue read
GetReference; default;    property Item[Index: Integer]: TValue read
GetValue write SetValue;
  Examples usages:
 type  TVertexArray = TAlignedArray;
 // and later
 var  Vertices: TVertexArray;begin
   Vertices.Length = 1000; // okay, request a page aligned memory 
Vertices[0].X := X; // okay, we are working with references 
Vertices.Item[1] := Vec3(X, Y, Z); // okay, we are setting a value 
Vertices.Length = 0; // clean up

 When the vertex array need to grow, it uses the POSIX posix_memalign (or
the _aligned_malloc on Windows) to request a 4 KB aligned and sized page
adequate to contain all the items. The newish allocate and release
mechanisms can further be used to simply the management of the
TAlignedArray type. ___
 fpc-devel maillist - fpc-devel@lists.freepascal.org [1]
 http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
[2]">http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

 

Links:
--
[1] mailto:fpc-devel@lists.freepascal.org
[2] http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Aligned dynamic arrays

2019-03-28 Thread Anthony Walter
Here is a brief follow up. I am working on other projects at the moment,
but I am confident this a simple solution. Please tell me if this somehow
will not fit you needs.

Create a new type that is compatible with Array where Array = type
array of T.
Define implcit conversions between the to types and similar methods
Create a Push and Pop methods, well as a read write Length property and two
indexers.
Indexer named Reference is default and provides a memory reference to Tn
Indexer named Item is available and provides a copy of Tn

So we would have ...

  TAlignedArray = record
type TReference = ^T;
type TValue = T;
FPage: Pointer;
FLength: Integer;
procedure SetLength(Value: Integer);
function GetReference(Index: Integer): TReference;
function GetItem(Index: Integer): TValue;
procedure SetItem(Index: Integer; const Value: TValue);
  public
procedure Push(const Item: TValue);
procedure Pop: TValue;
property Length: Integer read FLength write SetLength;
property Reference[Index: Integer]: TValue read GetReference; default;
property Item[Index: Integer]: TValue read GetValue write SetValue;

Examples usages:

type
  TVertexArray = TAlignedArray;

// and later

var
  Vertices: TVertexArray;
begin
  Vertices.Length = 1000; // okay, request a page aligned memory
  Vertices[0].X := X; // okay, we are working with references
  Vertices.Item[1] := Vec3(X, Y, Z); // okay, we are setting a value
  Vertices.Length = 0; // clean up


When the vertex array need to grow, it uses the POSIX posix_memalign (or
the _aligned_malloc on Windows) to request a 4 KB aligned and sized page
adequate to contain all the items. The newish allocate and release
mechanisms can further be used to simply the management of the
TAlignedArray type.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Aligned dynamic arrays

2019-03-28 Thread Sven Barth via fpc-devel

Am 28.03.2019 um 15:17 schrieb Ryan Joseph:



Also I don't think that a simple "do alignment or not" will be sufficient. What 
kind of alignment do you pick? What if the user needs more alignment? So it would 
probably be best to add a new SetLengthAligned of which the second argument is the 
alignment followed by the lengths.

That’s correct, there’s an alignment parameter also, not just a boolean. The 
header may need to include the desired alignment also for copy operations but 
I’m not sure yet.

Since the offset is going to be part of the header now (and possibly the 
desired alignment) does it matter that this will affect all dynamic arrays? 
It’s probably only 4 bytes but still worth considering.
I'm not a fan of introducing a separate header for this. And abusing 
some bits of the existing fields as flags just means that other parts of 
dynarr.inc have to be touched even though we avoided that by ordering it 
as [padding][header][data].

In dynarr.inc you then add a new setlength variant that takes an additional 
alignment parameter while the old one without alignment calls the new one with 
alignment 1.

Note: the compiler can call the new one for both variants, but the old one is 
required for bootstrapping, so you could surround that with {$if not 
defined(ver3_0) and not defined(ver3_2)}.

You mean if the compiler is < 3.0 then don’t parse the new SetLength variant?


No, I mean it like this:

=== code begin ===

procedure int_dynarray_setlength_aligned(var p : pointer;pti : pointer;
  dimcount : sizeint;dims : pdynarrayindex;alignment : 
longint);[external name 'FPC_DYNARR_SETLENGTH_ALIGNED'];


{$if defined(ver3_0) or defined(ver3_2)}
procedure fpc_dynarray_setlength(var p : pointer;pti : pointer;
  dimcount : sizeint;dims : 
pdynarrayindex);[Public,Alias:'FPC_DYNARR_SETLENGTH']; compilerproc;

begin
  int_dynarray_setlength_aligned(p,pti,dimcount,dims,1);
end;
{$endif}

=== code end ===

If the compiler always calls the aligned variant (on call less) then the 
one without alignment is only required for bootstrapping with 3.0.4 or 3.2.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Aligned dynamic arrays

2019-03-28 Thread Sven Barth via fpc-devel

Am 28.03.2019 um 18:41 schrieb Ryan Joseph:

Now I’m using “cd /rtl; make all FPC=/path/to/compiler” to build the RTL but 
this is obviously slow and unnecessary. Is there a quicker way to build just 
the unit which contains dynarr.inc and have all the objects files to be put in 
the correct location?
I don't see where this is slow... Even on my old PowerBook that time 
doesn't hinder me that much.


That said, you could try "make ../units/-/system.ppu" 
in the RTL directory of your target OS (e.g. for Linux in the rtl/linux 
directory and for Mac OS X in the rtl/darwin directory).


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Packed record integers and x86_86

2019-03-28 Thread Marco van de Voort


Op 2019-03-28 om 15:31 schreef Karoly Balogh (Charlie/SGR):

(Unless it also has to compile with say, Delphi.)
Everybody has {$pointermath on} is the include file included in every 
unit nowadays. Or at least I hope :-)

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Aligned dynamic arrays

2019-03-28 Thread Anthony Walter
Ryan, this is just a thought. Do you need the flat memory address to start
on an even 4 KB boundary or are you okay with the memory address starting
at any DWORD address and spanning an even 4 KB after that address?

In the latter case I have an easy solution for you. If the former I am
unsure how to allocate memory at a specific address but could create a
simple enough solution which may waste some space at the start yet give the
array a starting address of a number divisible evenly by 4 KB. Let me know
and I'll write an implementation which I am pretty sure you'll find either
solution more than adequate.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Aligned dynamic arrays

2019-03-28 Thread Christo Crause
On Thu, 28 Mar 2019, 20:34 Ryan Joseph,  wrote:

> Now I’m using “cd /rtl; make all FPC=/path/to/compiler” to build the RTL
> but this is obviously slow and unnecessary. Is there a quicker way to build
> just the unit which contains dynarr.inc and have all the objects files to
> be put in the correct location?
>

Dynarr.inc gets pulled into system.pp via system.inc. So the whole RTL
should be rebuilt anyway. Except of course if you only want to test your
changes without requiring anything else from the RTL. Then you can look at
the compiler command generated by make, system is the first unit to get
compiled, and copy that. There may of course be other ways too.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Aligned dynamic arrays

2019-03-28 Thread Ryan Joseph
Now I’m using “cd /rtl; make all FPC=/path/to/compiler” to build the RTL but 
this is obviously slow and unnecessary. Is there a quicker way to build just 
the unit which contains dynarr.inc and have all the objects files to be put in 
the correct location?


Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Packed record integers and x86_86

2019-03-28 Thread J. Gareth Moreton
 Heh, much better - thank you!

 On Thu 28/03/19 14:31 , "Karoly Balogh (Charlie/SGR)"
char...@scenergy.dfmk.hu sent:
 Hi, 

 On Thu, 28 Mar 2019, J. Gareth Moreton wrote: 

 > I think the official unsigned 32-bit integer type in Pascal is 
 > "LongWord". As others have said, be aware that pointers are 64-bit under

 > x64... that's kind of why it's called x64!  If you absolutely must have

 > a packed record with 32-bit types, I recommend changing Sender and 
 > Target to indices that are added to a base address. 
 > 
 > Similar to what Pierre said, change your Pointer code to something like 
 > this: 
 > 
 > for Indx := 0 to SizeOf(TTCPPackageHeader) - 1 do
Dec(Byte(Pointer(PtrUInt(@x) + Indx)^), ARollCount); 

 How about Dec(PByte(@x)[Indx], ARollCount); instead? That doesn't look 
 like an angry C programmer tried to convert some abomination to Pascal, 
 and works on all pointer sizes. 

 (Unless it also has to compile with say, Delphi.) 

 Charlie 

 ___
 fpc-devel maillist - fpc-devel@lists.freepascal.org [1]
 http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
[2]">http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

 

Links:
--
[1] mailto:fpc-devel@lists.freepascal.org
[2] http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Packed record integers and x86_86

2019-03-28 Thread Karoly Balogh (Charlie/SGR)
Hi,

On Thu, 28 Mar 2019, J. Gareth Moreton wrote:

> I think the official unsigned 32-bit integer type in Pascal is
> "LongWord". As others have said, be aware that pointers are 64-bit under
> x64... that's kind of why it's called x64!  If you absolutely must have
> a packed record with 32-bit types, I recommend changing Sender and
> Target to indices that are added to a base address.
>
> Similar to what Pierre said, change your Pointer code to something like
> this:
>
> for Indx := 0 to SizeOf(TTCPPackageHeader) - 1 do 
> Dec(Byte(Pointer(PtrUInt(@x) + Indx)^), ARollCount);

How about Dec(PByte(@x)[Indx], ARollCount); instead? That doesn't look
like an angry C programmer tried to convert some abomination to Pascal,
and works on all pointer sizes.

(Unless it also has to compile with say, Delphi.)

Charlie___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Aligned dynamic arrays

2019-03-28 Thread Ryan Joseph


> On Mar 28, 2019, at 4:17 AM, Sven Barth via fpc-devel 
>  wrote:
> 
> The order should be 
> 
> [padding] [header] [data]
> 
> with the offset being part of the header. This way you reduce the changes 
> needed to only those that allocate/free an array.

Yeah that’s probably the better idea because it’s less intrusive.

> Also I don't think that a simple "do alignment or not" will be sufficient. 
> What kind of alignment do you pick? What if the user needs more alignment? So 
> it would probably be best to add a new SetLengthAligned of which the second 
> argument is the alignment followed by the lengths. 

That’s correct, there’s an alignment parameter also, not just a boolean. The 
header may need to include the desired alignment also for copy operations but 
I’m not sure yet.

Since the offset is going to be part of the header now (and possibly the 
desired alignment) does it matter that this will affect all dynamic arrays? 
It’s probably only 4 bytes but still worth considering.

> 
> In dynarr.inc you then add a new setlength variant that takes an additional 
> alignment parameter while the old one without alignment calls the new one 
> with alignment 1.
> 
> Note: the compiler can call the new one for both variants, but the old one is 
> required for bootstrapping, so you could surround that with {$if not 
> defined(ver3_0) and not defined(ver3_2)}.

You mean if the compiler is < 3.0 then don’t parse the new SetLength variant?

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Aligned dynamic arrays

2019-03-28 Thread Sven Barth via fpc-devel
Ryan Joseph  schrieb am Do., 28. März 2019,
03:01:

> Here’s the basic structure:
>
> [header][padding][offset][head]
>
> [head] being the start of the elements (the pointer to the first element
> of the array) and aligned to the requested amount. Keep in mind the head is
> the pointer which is passed around so we need to subtract back from that in
> order to access the header, which contains the array high value and the
> refcount.
>

The order should be

[padding] [header] [data]

with the offset being part of the header. This way you reduce the changes
needed to only those that allocate/free an array.


> Look at the dynarr.inc in the /rtl directory to see what I’m talking
> about. Pretty hard to explain without seeing how Sven did things. :)
>

Most of that isn't my code. I only added Insert, Delete and Concat.


> >
> > The comment:
> > As for extending the array header, maybe introduce a new data type
> "aligned array".
> > So normal arrays do not have that field in there header.
>
> The plan was to make a “SetLengthAligned” or add an extra parameter to
> “SetLength”, i.e, SetLength(arr,100,true). I have no preference, what ever
> the compiler team wants.
>

Extending SetLength is not a good idea as that can take multiple lengths
for multi dimensional arrays.

Also I don't think that a simple "do alignment or not" will be sufficient.
What kind of alignment do you pick? What if the user needs more alignment?
So it would probably be best to add a new SetLengthAligned of which the
second argument is the alignment followed by the lengths.

In dynarr.inc you then add a new setlength variant that takes an additional
alignment parameter while the old one without alignment calls the new one
with alignment 1.

Note: the compiler can call the new one for both variants, but the old one
is required for bootstrapping, so you could surround that with {$if not
defined(ver3_0) and not defined(ver3_2)}.

Regards,
Sven

>
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel