digitalmars.D - core.runtime.GC memory alignment
- David Nadlinger (9/9) Oct 27 2013 The documentation for the GC.malloc family of functions mentions
- Peter Alexander (6/8) Oct 27 2013 It should guarantee the same as what malloc guarantees IMO:
- David Nadlinger (19/23) Oct 27 2013 Welö, except for the fact that "any kind of variable" is not
- Peter Alexander (5/15) Oct 27 2013 Correct me if I'm wrong, but my understanding is that align(N) on
- Andrei Alexandrescu (6/20) Oct 27 2013 Yah, something like that. I found align(NNN) underspecified and
- Peter Alexander (4/8) Oct 27 2013 Yeah I noticed the literal requirement as well and thought it was
- Manu (3/11) Oct 27 2013 I reported that as a deficiency over a year ago, I recall discussion, an...
- monarch_dodra (15/20) Oct 27 2013 In that case, we also need to specify how alignOf works. For
- John Colvin (6/17) Oct 27 2013 what does that even mean? Alignment means (address % alignment)
- monarch_dodra (7/24) Oct 27 2013 Observation shows that that's *how* align currently behaves
- Peter Alexander (9/32) Oct 27 2013 Alignment also means alignment within an object. It's more
- Manu (8/29) Oct 27 2013 I had a lot of informal conversations with Walter trying to get my head
- monarch_dodra (13/24) Oct 28 2013 But is that really what it means though? From the above
- David Nadlinger (14/25) Oct 28 2013 Like Manu, I think the only sane way for align() to behave is
- Manu (9/30) Oct 28 2013 Both should be true, if it's not, it's a bug.
- growler (16/43) Oct 28 2013 http://dlang.org/attribute.html#align
- growler (2/4) Oct 28 2013 To clarify, I mean the *alignment* of S is not affected by the
- Artur Skawina (6/9) Oct 29 2013 The alignment of an object must be at least as large as the max of the a...
- growler (2/16) Oct 29 2013 You're right, it would be nonsensical otherwise.
- Manu (8/52) Oct 28 2013 This is a strange test.
The documentation for the GC.malloc family of functions mentions that they return "an aligned block of managed memory from the garbage collector" without any further specification about what that level of alignment is supposed to be. What do we actually want to guarantee here? "Sufficient for any built-in type"? Note that my question is not about how the current implementation behaves, but about what the actual API guarantee should be. David
Oct 27 2013
On Sunday, 27 October 2013 at 15:49:00 UTC, David Nadlinger wrote:What do we actually want to guarantee here? "Sufficient for any built-in type"?It should guarantee the same as what malloc guarantees IMO: "The malloc() and calloc() functions return a pointer to the allocated memory that is suitably aligned for any kind of variable." I see no reason to diverge from that.
Oct 27 2013
On Sunday, 27 October 2013 at 16:19:28 UTC, Peter Alexander wrote:"The malloc() and calloc() functions return a pointer to the allocated memory that is suitably aligned for any kind of variable." I see no reason to diverge from that.Welö, except for the fact that "any kind of variable" is not well-defined for a language that supports user-defined alignment restrictions: --- struct Foo { align(8192) byte b; } template Seq(T...) { alias Seq = T; } void main() { import core.memory, core.stdc.stdio, core.stdc.stdlib; foreach (alloc; Seq!(malloc, GC.malloc)) { auto mem = cast(Foo*)alloc(Foo.sizeof); printf("%u\n", cast(uint)(cast(size_t)mem & (Foo.alignof - 1))); } } --- David
Oct 27 2013
On Sunday, 27 October 2013 at 17:53:14 UTC, David Nadlinger wrote:On Sunday, 27 October 2013 at 16:19:28 UTC, Peter Alexander wrote:Correct me if I'm wrong, but my understanding is that align(N) on a member only specifies the alignment *within the struct*, i.e. the member offsets. There's no guarantee that the Foo object itself will be aligned to 8192. It's not really memory alignment."The malloc() and calloc() functions return a pointer to the allocated memory that is suitably aligned for any kind of variable." I see no reason to diverge from that.Welö, except for the fact that "any kind of variable" is not well-defined for a language that supports user-defined alignment restrictions:
Oct 27 2013
On 10/27/13 12:51 PM, Peter Alexander wrote:On Sunday, 27 October 2013 at 17:53:14 UTC, David Nadlinger wrote:Yah, something like that. I found align(NNN) underspecified and underpowered for my work with allocators. As a simple matter, NNN must be a literal, not a compile-time expression. You can't even write e.g. align(size_t.alignof), which is fairly basic. AndreiOn Sunday, 27 October 2013 at 16:19:28 UTC, Peter Alexander wrote:Correct me if I'm wrong, but my understanding is that align(N) on a member only specifies the alignment *within the struct*, i.e. the member offsets. There's no guarantee that the Foo object itself will be aligned to 8192. It's not really memory alignment."The malloc() and calloc() functions return a pointer to the allocated memory that is suitably aligned for any kind of variable." I see no reason to diverge from that.Welö, except for the fact that "any kind of variable" is not well-defined for a language that supports user-defined alignment restrictions:
Oct 27 2013
On Sunday, 27 October 2013 at 20:30:05 UTC, Andrei Alexandrescu wrote:Yah, something like that. I found align(NNN) underspecified and underpowered for my work with allocators. As a simple matter, NNN must be a literal, not a compile-time expression. You can't even write e.g. align(size_t.alignof), which is fairly basic.Yeah I noticed the literal requirement as well and thought it was quite odd...
Oct 27 2013
On 28 October 2013 06:46, Peter Alexander <peter.alexander.au gmail.com>wrote:On Sunday, 27 October 2013 at 20:30:05 UTC, Andrei Alexandrescu wrote:I reported that as a deficiency over a year ago, I recall discussion, and thought it was to be fixed. Guess it didn't eventuate.Yah, something like that. I found align(NNN) underspecified and underpowered for my work with allocators. As a simple matter, NNN must be a literal, not a compile-time expression. You can't even write e.g. align(size_t.alignof), which is fairly basic.Yeah I noticed the literal requirement as well and thought it was quite odd...
Oct 27 2013
On Sunday, 27 October 2013 at 20:30:05 UTC, Andrei Alexandrescu wrote:Yah, something like that. I found align(NNN) underspecified and underpowered for my work with allocators. As a simple matter, NNN must be a literal, not a compile-time expression. You can't even write e.g. align(size_t.alignof), which is fairly basic. AndreiIn that case, we also need to specify how alignOf works. For example: struct S { align(128) int i; } static assert(S.alignOf == 128); If "align(N)" is supposed to only mean "alignement relative to the start of the struct", why the heck is S's "alignOf" 128? Also, (but I can't double check it right now), I seem to remember that there are odd things, like "ulong.alignOf == 8", yet if you declare one on the stack, you notice it's only 4 aligned (at least, on my win32 (I think) it is...)
Oct 27 2013
On Sunday, 27 October 2013 at 20:50:30 UTC, monarch_dodra wrote:On Sunday, 27 October 2013 at 20:30:05 UTC, Andrei Alexandrescu wrote:Yah, something like that. I found align(NNN) underspecified and underpowered for my work with allocators. As a simple matter, NNN must be a literal, not a compile-time expression. You can't even write e.g. align(size_t.alignof), which is fairly basic. Andrei"alignment relative to the start of the struct"what does that even mean? Alignment means (address % alignment) == 0 what would be the use case for guaranteeing ((fieldAddress - StructAddress) % alignment) == 0 that can't be just as easily done using normal alignment
Oct 27 2013
On Sunday, 27 October 2013 at 21:20:12 UTC, John Colvin wrote:On Sunday, 27 October 2013 at 20:50:30 UTC, monarch_dodra wrote:Observation shows that that's *how* align currently behaves anyways: http://forum.dlang.org/thread/difcpyoejpbngzpoynce forum.dlang.org#post-nhrvixioystchhdpmakg:40forum.dlang.org Its like its incorrectly named, and actually specifies "paking". However, the two concepts seem packed into one, resulting in some confusing semantics and bahaviors.On Sunday, 27 October 2013 at 20:30:05 UTC, Andrei Alexandrescu wrote:Yah, something like that. I found align(NNN) underspecified and underpowered for my work with allocators. As a simple matter, NNN must be a literal, not a compile-time expression. You can't even write e.g. align(size_t.alignof), which is fairly basic. Andrei"alignment relative to the start of the struct"what does that even mean? Alignment means (address % alignment) == 0 what would be the use case for guaranteeing ((fieldAddress - StructAddress) % alignment) == 0 that can't be just as easily done using normal alignment
Oct 27 2013
On Sunday, 27 October 2013 at 21:20:12 UTC, John Colvin wrote:On Sunday, 27 October 2013 at 20:50:30 UTC, monarch_dodra wrote:Alignment also means alignment within an object. It's more commonly referred to as "padding" but it's a form of alignment.On Sunday, 27 October 2013 at 20:30:05 UTC, Andrei Alexandrescu wrote:Yah, something like that. I found align(NNN) underspecified and underpowered for my work with allocators. As a simple matter, NNN must be a literal, not a compile-time expression. You can't even write e.g. align(size_t.alignof), which is fairly basic. Andrei"alignment relative to the start of the struct"what does that even mean? Alignment means (address % alignment) == 0what would be the use case for guaranteeing ((fieldAddress - StructAddress) % alignment) == 0 that can't be just as easily done using normal alignmentUsually it's done when you are reading binary files that are in some particular format that may or may not pack data in the same way that you'd get from normal alignment.If "align(N)" is supposed to only mean "alignement relative to the start of the struct", why the heck is S's "alignOf" 128? Also, (but I can't double check it right now), I seem to remember that there are odd things, like "ulong.alignOf == 8", yet if you declare one on the stack, you notice it's only 4 aligned (at least, on my win32 (I think) it is...)I believe .alignof also refers to structure alignment, it doesn't guarantee alignment in memory or on the stack (as you've discovered).
Oct 27 2013
On 28 October 2013 06:50, monarch_dodra <monarchdodra gmail.com> wrote:On Sunday, 27 October 2013 at 20:30:05 UTC, Andrei Alexandrescu wrote:I had a lot of informal conversations with Walter trying to get my head around the details here. To my recollection, the intent was that it should behave like C, and that S.alignof must certainly == 128 in that case. It can't work otherwise. Alignment must be inherited by parent structures. I also recall commenting on that case with ulong. On most architectures it only needs to be 4 byte aligned, but that one is arch specific.Yah, something like that. I found align(NNN) underspecified and underpowered for my work with allocators. As a simple matter, NNN must be a literal, not a compile-time expression. You can't even write e.g. align(size_t.alignof), which is fairly basic. AndreiIn that case, we also need to specify how alignOf works. For example: struct S { align(128) int i; } static assert(S.alignOf == 128); If "align(N)" is supposed to only mean "alignement relative to the start of the struct", why the heck is S's "alignOf" 128? Also, (but I can't double check it right now), I seem to remember that there are odd things, like "ulong.alignOf == 8", yet if you declare one on the stack, you notice it's only 4 aligned (at least, on my win32 (I think) it is...)
Oct 27 2013
On Monday, 28 October 2013 at 02:44:54 UTC, Manu wrote:I had a lot of informal conversations with Walter trying to get my head around the details here. To my recollection, the intent was that it should behave like C, and that S.alignof must certainly == 128 in that case. It can't work otherwise. Alignment must be inherited by parent structures.But is that really what it means though? From the above conversation, it would instead appear to mean that: struct S { int i; align(128) int j; } in this case, the *padding* needed until we reach j is 128 bytes. It doesn't mean that S itself need to be 128 aligned.I also recall commenting on that case with ulong. On most architectures it only needs to be 4 byte aligned, but that one is arch specific.Does it make sense (and should it be illegal) in that case to have anything with alignment > 8 ? I just don't see how something like "malloc" would be able to deal with them otherwise... ?
Oct 28 2013
On Monday, 28 October 2013 at 18:33:49 UTC, monarch_dodra wrote:But is that really what it means though? From the above conversation, it would instead appear to mean that: struct S { int i; align(128) int j; } in this case, the *padding* needed until we reach j is 128 bytes.Like Manu, I think the only sane way for align() to behave is like GCC's/Clang's "aligned" attribute, which would both add padding such that j is at offset 128, and ensure that any variables of type S are aligned to 128 bytes as well.I just don't see how something like "malloc" would be able to deal with them otherwise... ?Raw system malloc(), without knowing anything about the type, obviously cannot honor any special alignment requests. Thus, usually special primitives exist which accept an additional parameter to specify the target alignment (cf. the std.allocator discussion). If you really want to use C malloc() for your 256-byte-aligned objects, you have to handle things yourself, e.g. by over-allocating and then adjusting the base pointer or similar strategies. David
Oct 28 2013
On 29 October 2013 04:33, monarch_dodra <monarchdodra gmail.com> wrote:On Monday, 28 October 2013 at 02:44:54 UTC, Manu wrote:Both should be true, if it's not, it's a bug. I also recall commenting on that case with ulong. On most architectures itI had a lot of informal conversations with Walter trying to get my head around the details here. To my recollection, the intent was that it should behave like C, and that S.alignof must certainly == 128 in that case. It can't work otherwise. Alignment must be inherited by parent structures.But is that really what it means though? From the above conversation, it would instead appear to mean that: struct S { int i; align(128) int j; } in this case, the *padding* needed until we reach j is 128 bytes. It doesn't mean that S itself need to be 128 aligned.Well SIMD vector's require at least 16 byte alignment, so say goodbye to a major subsection of your CPU ;) I've never seen a malloc implementation that returns memory that is less than 16 byte aligned. If you expect higher alignment, typically you use OS provided AliognedAlloc primitives, or you use tricks like overallocating and offseting.only needs to be 4 byte aligned, but that one is arch specific.Does it make sense (and should it be illegal) in that case to have anything with alignment > 8 ? I just don't see how something like "malloc" would be able to deal with them otherwise... ?
Oct 28 2013
On Tuesday, 29 October 2013 at 00:45:59 UTC, Manu wrote:On 29 October 2013 04:33, monarch_dodra <monarchdodra gmail.com> wrote:http://dlang.org/attribute.html#align --- The alignment for the fields of an aggregate does not affect the alignment of the aggregate itself - that is affected by the alignment setting outside of the aggregate. align (2) struct S { align (1): byte a; // placed at offset 0 int b; // placed at offset 1 long c; // placed at offset 5 } auto sz = S.sizeof; // 14 --- My understanding of that is S is not affected by the alignment of its fields.On Monday, 28 October 2013 at 02:44:54 UTC, Manu wrote:Both should be true, if it's not, it's a bug.I had a lot of informal conversations with Walter trying to get my head around the details here. To my recollection, the intent was that it should behave like C, and that S.alignof must certainly == 128 in that case. It can't work otherwise. Alignment must be inherited by parent structures.But is that really what it means though? From the above conversation, it would instead appear to mean that: struct S { int i; align(128) int j; } in this case, the *padding* needed until we reach j is 128 bytes. It doesn't mean that S itself need to be 128 aligned.
Oct 28 2013
My understanding of that is S is not affected by the alignment of its fields.To clarify, I mean the *alignment* of S is not affected by the alignment of its fields.
Oct 28 2013
On 10/29/13 06:36, growler wrote:The alignment of an object must be at least as large as the max of the alignment of all fields that it contains, obviously. The object layout never changes; using a smaller alignment for the parent object would make it impossible to guarantee the specified field alignment. arturMy understanding of that is S is not affected by the alignment of its fields.To clarify, I mean the *alignment* of S is not affected by the alignment of its fields.
Oct 29 2013
On Tuesday, 29 October 2013 at 12:31:00 UTC, Artur Skawina wrote:On 10/29/13 06:36, growler wrote:You're right, it would be nonsensical otherwise.The alignment of an object must be at least as large as the max of the alignment of all fields that it contains, obviously. The object layout never changes; using a smaller alignment for the parent object would make it impossible to guarantee the specified field alignment. arturMy understanding of that is S is not affected by the alignment of its fields.To clarify, I mean the *alignment* of S is not affected by the alignment of its fields.
Oct 29 2013
On 29 October 2013 13:47, growler <growlercab gmail.com> wrote:On Tuesday, 29 October 2013 at 00:45:59 UTC, Manu wrote:This is a strange test. It looks like your align(1) is intended to mean pack(1), and if that is the case, then the observed sizeof is correct. with pack(1), the size would be 8+4+1 = 13, but then the struct marked align(2) must be padded to a multiple of it's alignment, so 14. What you observe is probably correct, except I don't think the use of align(1) to mean pack(1) is right. That should raise discussion...On 29 October 2013 04:33, monarch_dodra <monarchdodra gmail.com> wrote: On Monday, 28 October 2013 at 02:44:54 UTC, Manu wrote:http://dlang.org/attribute.**html#align<http://dlang.org/attribute.html#align> --- The alignment for the fields of an aggregate does not affect the alignment of the aggregate itself - that is affected by the alignment setting outside of the aggregate. align (2) struct S { align (1): byte a; // placed at offset 0 int b; // placed at offset 1 long c; // placed at offset 5 } auto sz = S.sizeof; // 14 --- My understanding of that is S is not affected by the alignment of its fields.I had a lot of informal conversations with Walter trying to get my headBoth should be true, if it's not, it's a bug.around the details here. To my recollection, the intent was that it should behave like C, and that S.alignof must certainly == 128 in that case. It can't work otherwise. Alignment must be inherited by parent structures.But is that really what it means though? From the above conversation, it would instead appear to mean that: struct S { int i; align(128) int j; } in this case, the *padding* needed until we reach j is 128 bytes. It doesn't mean that S itself need to be 128 aligned.
Oct 28 2013