c++c++11alignmentalignas

Do I need alignment in C++?


I am sure I do. The matrix library Eigen3 is likely much faster than any of my own matrix implementations thanks to alignment.

I recently started investigating on alignment using C++. I stumbled on the alignas and alignof functions, and decided to do some tests.

My first finding was that members of a struct get aligned automatically. Let's take the following struct as an example:

struct MyStruct
{
    char m_c; // 1 byte
    double m_x; // 8 bytes
};

and compare with this one:

struct MyAlignedStruct
{
    char m_c; // 1 byte
    alignas(8) double m_x; // 8 bytes
};

where I used alignas instead of adding a padding member (char[7]), which, according to my understanding, is equivalent.

Now, the memory viewer for both structs showed the following:

62 00 00 00 8e a8 79 35 00 00 00 00 00 00 10 40 // MyStruct
62 ff ff ff 24 00 00 00 00 00 00 00 00 00 10 40 // MyAlignedStruct

The first byte corresponds to a char ('b'). When using Mystruct, the next 7 bytes are filled with something, and the 8 last bytes represent the double. When using MyAlignedStruct, something very similar occurs. The sizeof() function returns 16 bytes for both structs (I expected 9 bytes for MyStruct).

So here comes my first question: Why do I need alignas if the compiler aligns on its own?

My second finding was that alignas(..) does not speed up my program. My experiment was the following. Imagine the following simple struct:

struct Point
{
    double m_x, m_y, m_z;
};

If I fill a vector with instances of that struct, and assuming the first instance is 32-byte aligned, each struct would occupy 24 bytes, and the sequence of bytes would not be 32-byte aligned anymore. Honestly, I'm not sure how speed could be increased by aligning, otherwise, I most probably wouldn't be writing here. Nevertheless, I used alignas to obtain the following struct:

alignas(32) struct Point
{
    double m_x, m_y, m_z;
};

Now, contiguous instances of Point would start on a multiple of 32 bytes. I tested both versions: after filling a huge vector with instances of the structs, I summed all the doubles and recorded the time. I found no differences between the 32-byte aligned struct and the other one.

So my second question is the same as my first one: why do I need alignas?


Solution

  • Why do I need alignas if the compiler aligns on its own?

    A few reasons off the top of my head:

    1. The compiler might be configured to pack structs, as described here:

      Force C++ structure to pack tightly

      but you want some specific struct to have aligned members

    2. You want alignment that's beyond what the type requires, e.g.

      alignas(1024) struct MyStruct
      {
          char m_c; // 1 byte
          alignas(32) double m_x; // 8 bytes
      };
      

      This could be due to hardware constraints, e.g. you have a card which can grab things from memory at a resolution of 1024 pages; and then, on that card, data accesses are done in units of 32 bytes. The example will match those requirements instead of having to insert dummy fields.

    3. Type punning/slicing: You might get an address to an array of:

      struct s1
      {
          char m_c;
          uint32_t m_d;
          char m_e;
      };
      

      but I was actually using a

      struct s2
      {
          char m_c;
          mystery_type_with_size_64_bits m_d;
          char m_e;
      };
      

      so even though you want to work with m_d as an uint32_t, but you also need to get m_e right.