Re: [fpc-devel] Aligned dynamic arrays
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
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
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
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
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
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
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
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
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
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
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
> 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
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