0

Consider the following code:

// Thin/POD struct
struct Data {
 __m256d a;
 __m256d b;
};
// Thick base class
class Base {
  // ...
};
// Thick derived class
class Derived : public Base {
  Data data;
  // ...
};

Is there a way to ensure that Derived::data member is properly aligned for AVX (32 byte alignment)? Because the derived class has a base, there doesn't seem to be a way for something like class alignas(32) Derived and placing data as the first member of Derived.

Derived is currently allocated on the stack only, but it may need heap allocation later too.

UPDATE: The compiler is MSVC++2017 , so C++11/14/17 is (partially) supported.

Serge Rogatch
  • 13,865
  • 7
  • 86
  • 158
  • 1
    As far as I know, alignment constraints are propagated from individual fields to the aggregates that contain them. Therefore, the alignment constraints of an `__m256d` field should be propagated to the `Data` struct, and then again to the `Derived` struct. But you could ensure that the `Data` field is aligned by explicitly annotating it with `alignas(__m256d)` (or, if you don't have C++11 support, whatever the syntax is for the compiler you're using). – Cody Gray - on strike Jul 02 '17 at 05:54
  • Did you notice any mis-alignment? It is supposed to work automatically, possibly leaving padding space in the middle of the object. Dynamic allocation is another matter, and apparently VC++ does not support "Over-aligned dynamic memory allocation" yet. – Marc Glisse Jul 02 '17 at 06:15
  • @MarcGlisse, no, I haven't noticed any misalignment yet. But I would like to know about potential bugs too, before they happen. Can you point some link about MSVC++'s (un)support of "Over-aligned dynamic memory allocation"? I can't find it on the internet, except generic http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0035r1.html – Serge Rogatch Jul 02 '17 at 06:26
  • https://blogs.msdn.microsoft.com/vcblog/2017/05/10/c17-features-in-vs-2017-3/ – Marc Glisse Jul 02 '17 at 06:27
  • Thanks, it's now clear to me. Would someone like to combine these comments into an answer? – Serge Rogatch Jul 02 '17 at 06:40
  • Oops, not everything clear. Isn't it possible to achieve properly aligned dynamic allocations by placing `data` into an `std::aligned_storage`? Like `typename std::aligned_storage::type data;` in `Derived` class? – Serge Rogatch Jul 02 '17 at 06:44
  • How is that dynamic? The problem before C++17 is that new returns memory with an alignment that does not depend on the type. – Marc Glisse Jul 02 '17 at 07:12
  • @MarcGlisse , I understood that `std::aligned_storage` at compile time reserves more memory than `sizeof(Data)` - something close to `sizeof(Data) + sizeof(__m256d)`. Then at run time it looks at the address of the first byte reserved and uses for storage of `Data` the first subsequent address which is a multiple of `sizeof(__m256d)`. – Serge Rogatch Jul 02 '17 at 07:34
  • I don't think that's done automatically, no. – Marc Glisse Jul 02 '17 at 08:12

1 Answers1

1

For objects on the stack, alignment is properly propagated from fields to the enclosing data structure.

Furthermore, alignas can be used on data members

struct S{};

struct T
{
    char c;
    S alignas(32) s;
};

For objects on the heap, alignment isn't guaranteed automatically prior to C++17.

In C++17 there is several alternatives to allocating aligned memory on the heap.

struct alignas(32) S {};

auto s1 = std::aligned_alloc(alignof(S), sizeof(S));

auto s2 = new S; // has the meaning of...
auto s2_ = new (std::align_val_t(alignof(S))) S; 

auto sz = alignof(S) + sizeof(S) - 1;
auto s3 = std::malloc(sz);
std::align(alignof(S), sizeof(S), s3, sz);

Reference:
aligned_alloc
new
align

As a personal favor and world peace, please don't use std::align.

Passer By
  • 19,325
  • 6
  • 49
  • 96