Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2023-03

Cache-line alignment for records

16 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Matias Ezequiel Vara Larsen

Hello everyone,

Apologies in the case this subject has been already discussed. I require that some global variables be cache-line aligned. This is a requirement for per-CPU variables that are statically defined to prevent cache ping-pong. Is there any way to do this at fpc when the record is declared? This would tell compiler to align every definition. Currently, I can simply allocate memory and do the alignment afterwards, however, I can't do this for all the cases.

Thanks, Matias.

Jonas Maebe
to Matias Ezequiel Vara Larsen
Matias Ezequiel Vara Larsen wrote 5 lines
Apologies in the case this subject has been already discussed. I require that some global variables be cache-line aligned. This is a requirement for per-CPU variables that are statically defined to prevent cache ping-pong. Is there any way to do this at fpc when the record is declared?
{$push}
{$codealign varmin=16}
{$codealign constmin=16}
const
   constdata: array[0..3] of longint = (1,2,3,4);
var
   x: array[0..15] of longint;
{$pop}

However, the maximum alignment you can specify this way is limited per target (hardcoded in the compiler). In 3.2.x, it's 16 bytes for most desktop targets. On 3.3.x, it's 64 bytes for most desktop targets.

Jonas

denisgolovan
to Jonas Maebe
Show quoted text 5 lines
However, the maximum alignment you can specify this way is limited per target (hardcoded in the compiler). In 3.2.x, it's 16 bytes for most desktop targets. On 3.3.x, it's 64 bytes for most desktop targets. Jonas

But it's still not possible to attach alignment to type itself instead of variable, right?

-- Regards,
Denis Golovan

Matias Ezequiel Vara Larsen
to Jonas Maebe: It is possible (https://gitlab.com/freepascal.org/fpc/source/-/blob/main/tests/test/talign…

Hello,

Jonas Maebe wrote 8 lines
On 27/03/2023 21:25, denisgolovan via fpc-pascal wrote: > But it's still not possible to attach alignment to type itself instead of variable, right? It is possible (https://gitlab.com/freepascal.org/fpc/source/-/blob/main/tests/test/talignrec1.pp), but it is subject to the same limitations when declaring variables of those types.

Thanks, this is what I was looking for, however, when the type is defined as an array, only the [0] element is aligned. I was expecting that each element in the array would be aligned.

Matias

Sven Barth
to Matias Ezequiel Vara Larsen

Matias Ezequiel Vara Larsen via fpc-pascal
schrieb am Mi., 29. März 2023, 00:27:

Show quoted text 20 lines
Hello, On Mon, Mar 27, 2023 at 09:35:38PM +0200, Jonas Maebe via fpc-pascal wrote: > On 27/03/2023 21:25, denisgolovan via fpc-pascal wrote: > > > But it's still not possible to attach alignment to type itself instead of variable, right? > > It is possible ( https://gitlab.com/freepascal.org/fpc/source/-/blob/main/tests/test/talignrec1.pp ), > but it is subject to the same limitations when declaring variables of those > types. > Thanks, this is what I was looking for, however, when the type is defined as an array, only the [0] element is aligned. I was expecting that each element in the array would be aligned.

No, array types are defined as never having padding between the elements. You need to make sure that the element is appropriately sized then.

Regards,
Sven

Matias Ezequiel Vara Larsen
to Sven Barth
Sven Barth wrote 27 lines
Matias Ezequiel Vara Larsen via fpc-pascal schrieb am Mi., 29. März 2023, 00:27: > Hello, > > On Mon, Mar 27, 2023 at 09:35:38PM +0200, Jonas Maebe via fpc-pascal wrote: > > On 27/03/2023 21:25, denisgolovan via fpc-pascal wrote: > > > > > But it's still not possible to attach alignment to type itself instead > of variable, right? > > > > It is possible ( > https://gitlab.com/freepascal.org/fpc/source/-/blob/main/tests/test/talignrec1.pp > ), > > but it is subject to the same limitations when declaring variables of > those > > types. > > > > Thanks, this is what I was looking for, however, when the type is > defined as an array, only the [0] element is aligned. I was expecting > that each element in the array would be aligned. > No, array types are defined as never having padding between the elements. You need to make sure that the element is appropriately sized then.

Thanks for the comment. I will pad those records used for per-cpu variables so they fit in different cache-lines when defined as an array.

Matias

Matias Ezequiel Vara Larsen
to Jonas Maebe: {$push} {$codealign varmin=16} {$codealign constmin=16} const constdata: array[0..3] of…
Jonas Maebe wrote 21 lines
On 27/03/2023 09:28, Matias Ezequiel Vara Larsen via fpc-pascal wrote: > Apologies in the case this subject has been already discussed. I require > that some global variables be cache-line aligned. This is a requirement > for per-CPU variables that are statically defined to prevent cache > ping-pong. Is there any way to do this at fpc when the record is > declared? {$push} {$codealign varmin=16} {$codealign constmin=16} const constdata: array[0..3] of longint = (1,2,3,4); var x: array[0..15] of longint; {$pop} However, the maximum alignment you can specify this way is limited per target (hardcoded in the compiler). In 3.2.x, it's 16 bytes for most desktop targets. On 3.3.x, it's 64 bytes for most desktop targets.

I've tried this (fpc 3.2.0) and it correctly aligns to 64 bytes (x86 cacheline):

{$push}
{$codealign varmin=64}
var
   x: array[0..15] of longint;
{$pop}

The generated assembler is:

.section .bss
.balign 64
.type U_$P$PROGRAM_$$_X,@object
.size U_$P$PROGRAM_$$_X,64
U_$P$PROGRAM_$$_X:
.zero 64

Is it possible to define "varmin" as a constant or symbol instead of using the actual value each time?

Matias

Hairy Pixels
to Sven Barth: Matias Ezequiel Vara Larsen via fpc-pascal schrieb am Mi., 29. März 2023, 00:27: No,…
On Mar 29, 2023, at 1:33 PM, Sven Barth via fpc-pascal wrote: No, array types are defined as never having padding between the elements. You need to make sure that the element is appropriately sized then.

Wouldn’t that be better for performance if each element was padded to align with the cache? That seems like something the compiler could do easily for you behind the scenes. I may not understand the need to "align the elements on the cache” though.

Regards,
Ryan Joseph

Matias Ezequiel Vara Larsen
to Sven Barth: Matias Ezequiel Vara Larsen via fpc-pascal schrieb am Mi., 29. März 2023, 00:27: No,…
Sven Barth wrote 27 lines
Matias Ezequiel Vara Larsen via fpc-pascal schrieb am Mi., 29. März 2023, 00:27: > Hello, > > On Mon, Mar 27, 2023 at 09:35:38PM +0200, Jonas Maebe via fpc-pascal wrote: > > On 27/03/2023 21:25, denisgolovan via fpc-pascal wrote: > > > > > But it's still not possible to attach alignment to type itself instead > of variable, right? > > > > It is possible ( > https://gitlab.com/freepascal.org/fpc/source/-/blob/main/tests/test/talignrec1.pp > ), > > but it is subject to the same limitations when declaring variables of > those > > types. > > > > Thanks, this is what I was looking for, however, when the type is > defined as an array, only the [0] element is aligned. I was expecting > that each element in the array would be aligned. > No, array types are defined as never having padding between the elements. You need to make sure that the element is appropriately sized then.

So if I have a type like:

test = record
  r: DWord;
  s: Word;
end;

Then, I define the variable `nada` as an array of `test` type:

var
  nada: array[0..2] of test;

Is the element aligned to 4-bytes?

Thanks, Matias.

Matias Ezequiel Vara Larsen
to Hairy Pixels: Wouldn’t that be better for performance if each element was padded to align with the…
Hairy Pixels wrote 8 lines
> On Mar 29, 2023, at 1:33 PM, Sven Barth via fpc-pascal wrote: > > No, array types are defined as never having padding between the elements. You need to make sure that the element is appropriately sized then. > Wouldn’t that be better for performance if each element was padded to align with the cache? That seems like something the compiler could do easily for you behind the scenes. I may not understand the need to "align the elements on the cache” though.

I do not think you would like to have everything aligned to the cacheline. This use-case requires it because each element in the array will be accessed from a different CPU and you would try to prevent cache ping-pong, i.e., sharing the same cacheline between different cpu's cache.

Matias

Jonas Maebe
to Matias Ezequiel Vara Larsen: So if I have a type like: test = record r: DWord; s: Word; end; Then, I define the…
Matias Ezequiel Vara Larsen wrote 13 lines
So if I have a type like: test = record r: DWord; s: Word; end; Then, I define the variable `nada` as an array of `test` type: var nada: array[0..2] of test; Is the element aligned to 4-bytes?

Records always get padded to a multiple of their internal alignment requirement. Unless you're on a system where the default packrecords value is 2 (msdos-i8086 has that probably), the above record's internal field alignment is 4 and hence its size will also be padded to a multiple of 4.

Jonas

Ched
to Jonas Maebe

Hello,

Ok for the records for internal calculations. But sometimes, records are used for reading/writing structured files. Does "packed" in "packed array" and "packed record" always forbid the compiler to play with alignments ?

Kindest regards, Ched'

Le 29.03.23 à 21:07, Jonas Maebe via fpc-pascal a écrit :

Show quoted text 21 lines
On 29/03/2023 16:00, Matias Ezequiel Vara Larsen via fpc-pascal wrote: > So if I have a type like: > > test = record >    r: DWord; >    s: Word; > end; > > Then, I define the variable `nada` as an array of `test` type: > > var >    nada: array[0..2] of test; > > Is the element aligned to 4-bytes? Records always get padded to a multiple of their internal alignment requirement. Unless you're on a system where the default packrecords value is 2 (msdos-i8086 has that probably), the above record's internal field alignment is 4 and hence its size will also be padded to a multiple of 4. Jonas
Ralf Quint
to Ched
Ched wrote 6 lines
Hello, Ok for the records for internal calculations. But sometimes, records are used for reading/writing structured files. Does "packed" in "packed array" and "packed record" always forbid the compiler to play with alignments ?

If that record/array is specifically defined as "packed", then yes, of course. However, arrays/records that are no so defined should be aligned...

Ralf

Matias Ezequiel Vara Larsen
to Jonas Maebe: Records always get padded to a multiple of their internal alignment requirement. Unless…
Jonas Maebe wrote 20 lines
On 29/03/2023 16:00, Matias Ezequiel Vara Larsen via fpc-pascal wrote: > So if I have a type like: > > test = record > r: DWord; > s: Word; > end; > > Then, I define the variable `nada` as an array of `test` type: > > var > nada: array[0..2] of test; > > Is the element aligned to 4-bytes? Records always get padded to a multiple of their internal alignment requirement. Unless you're on a system where the default packrecords value is 2 (msdos-i8086 has that probably), the above record's internal field alignment is 4 and hence its size will also be padded to a multiple of 4.

Thanks for the clarification,

Matias