How to tell the maximum data alignment requirement in C++ - c++

Referencing this question and answer Memory alignment : how to use alignof / alignas? "Alignment is a restriction on which memory positions a value's first byte can be stored." Is there a portable way in C++ to find out the highest granularity of alignment that is required for instructions not to fault (for example in ARM)? Is alignof(intmax_t) sufficient since its the largest integer primitive type?
Further, how does something in malloc align data to a struct's boundaries? For example if I have a struct like so
alignas(16) struct SomethingElse { ... };
the SomethingElse struct is required to be aligned to a boundary that is a multiple of 16 bytes. Now if I request memory for a struct from malloc like so
SomethingElse* ptr = malloc(sizeof(SomethingElse));
Then what happens when malloc returns a pointer that points to an address like 40? Is that invalid since the pointer to SomethingElse objects must be a multiple of 16?

How to tell the maximum data alignment requirement in C++
There is std::max_align_t which
is a POD type whose alignment requirement is at least as strict (as large) as that of every scalar type.
Vector instructions may use array operands that require a higher alignment than any scalar. I don't know if there is a portable way to find out the the upper bound for that.
To find the alignment requirement for a particular type, you can use alignof.
Further, how does something in malloc align data to a struct's boundaries?
malloc aligns to some boundary that is enough for any scalar. In practice exactly the same as std::max_align_t.
It won't align correctly for "overaligned" types. By overaligned, I mean a type that has higher alignment requirement than std::max_align_t.
Then what happens when malloc returns a pointer that points to an address like 40?
Dereferencing such SomethingElse* would be have undefined behaviour.
Is that invalid since the pointer to SomethingElse objects must be a multiple of 16?
Yes.
how even would one go about fixing that? There is no way to tell malloc the alignment that you want right?
To allocate memory for overaligned types, you need std::aligned_alloc which is to be introduced in C++17.
Until then, you can use platform specific functions like posix_memalign or you can over allocate with std::malloc (allocate the alignment - 1 worth of extra bytes), then use std::align to find the correct boundary. But then you must keep track of both the start of the buffer, and the start of the memory block separately.

You might be looking for std::max_align_t

Related

Handling alignment in a custom memory pool

I'm trying to make a memory pool class that allows me to return pointers from within a char* array, and cast them as various pointer. Very very simplified implementation:
class Mempool
{
char* mData=new char[1000];
int mCursor=0;
template <typename vtype>
vtype* New()
{
vtype* aResult=(vtype*)mData[mCursor];
mCursor+=sizeof(vtype);
return aResult;
}
};
(Remember, it's not intended to be dynamic, this is just random access memory that I only need for a short time and then it can all be tossed)
Here's my issue: I know that on some systems (iOS, at least) a float* has to be aligned. I assume the alignment is obtained via alignof(float)... but I can't ever be sure of the alignment of the initial char*'s allocation could be anywhere, because alignof(char) is 1.
What can I do to make sure that in my New() function, my mCursor is advanced to a proper alignment for the requested object?
alignof(std::max_align_t) will tell you the alignment required on your platform for standard functions like malloc(). You should use that if you don't know what alignment requirements the users of your allocator will have.
Simply round sizeof(vtype) up to the nearest multiple of alignof(std::max_align_t) when you increment mCursor.
Or for perhaps a little more efficiency, increment mCursor as you do now, then round it up as needed when the user requests an allocation. When allocating an object of size 2 for example, you know that 2-byte alignment is sufficient, you don't need the full alignof(std::max_align_t). You can use alignof(vtype) for this, to avoid wasted space if users allocate small objects next to each other.
As for this:
I can't ever be sure of the alignment of the initial char*'s allocation could be anywhere, because alignof(char) is 1
You can be sure: new char[N] will always be aligned to at least alignof(std::max_align_t). But my second approach (pad when New is called) does not rely on this assumption.

Memory alignment, structs and malloc

It's a bit hard to formulate what I want to know in a single question, so I'll try to break it down.
For example purposes, let's say we have the following struct:
struct X {
uint8_t a;
uint16_t b;
uint32_t c;
};
Is it true that the compiler is guaranteed to never rearrange the order of X's members, only add padding where necessary? In other words, is it always true that offsetof(X, a) < offsetof(X, c)?
Is it true that the compiler will pick the largest alignment among X's members and use it to align objects of type X (i.e. addresses of X instances will be divisible by the largest alignment among X's members)?
Since malloc does not know anything about the type of objects that we're going to store when we allocate a buffer, how does it choose an alignment for the returned address? Does it simply return an adress that is divisible by the largest alignment possible (in which case, no matter what structure we put in the buffer, the memory accesses will always be aligned)?
Yes
No, the compiler will use its knowledge of the target host hardware to select the best alignment.
See question 2.
Since malloc does not know anything about the type of objects that we're going to store when we allocate a buffer, how does it choose an alignment for the returned address?
malloc(3) returns "memory that is suitably aligned for any kind of variable."
Does it simply return an adress that is divisible by the largest alignment possible (in which case, no matter what structure we put in the buffer, the memory accesses will always be aligned)?
Yes, but watch your compliance with the strict aliasing rule.
The compiler will do whatever is most beneficial on that computer in the largest number of circumstances. On most platforms loading bus wide values on bus width offsets is fastest.
That means that generally on 32-bit computers compilers will chose to align 32-bit numbers on 4 byte offsets. On 64-bit computers 64-bit values are aligned on 8 byte offsets.
On most computers smaller values like 8-bit and 16-bit values are slower to load. Probably all 4 or 8 bytes around it are loaded and the byte or two bytes you need are masked off.
When you have special circumstances you can override the compiler by specifying the alignment and the padding. You might do this when you know fast loading is not important, but you really want to pack the data tightly. Or when you are playing very subtle tricks with casting and unions.
Memory allocation routines on almost any modern computer will always return memory that is aligned on at least the bus width of the platform ( e.g. 4 or 8 bytes ) - or even more - like 16 byte alignment.
When you call "malloc" you are responsible for knowing the size of the structures you need. Luckily the compiler will tell you the size of any structure with "sizeof". That means that if you pack a structure to save memory, sizeof will return a smaller value than an unpacked structure. So you really will save memory - if you are allocating small structures in large arrays of them.
If you allocate small packed structures one at a time - then yes - if you pack them or not it won't make any difference. That is because when you allocate some odd small piece of memory - the allocator will actually use significantly more memory than that. It will allocate an convenient sized block of memory for you, and then an additional block of memory for itself to keep track of you allocation.
Which is why if you care about memory use and want to pack your structures - you definitely don't want to allocate them one at time.

Is std::make_unique<T[]> required to return aligned memory?

Is the memory owned by the unique pointer array_ptr:
auto array_ptr = std::make_unique<double[]>(size);
aligned to a sizeof(double) alignof(double) boundary (i.e. is it required by the std to be correctly aligned)?
Is the first element of the array the first element of a cache line?
Otherwise: what is the correct way of achieving this in C++14?
Motivation (update): I plan to use SIMD instructions on the array and since cache lines are the basic unit of memory on every single architecture that I know of I'd rather just allocate memory correctly such that the first element of the array is at the beginning of a cache line. Note that SIMD instructions work as long as the elements are correctly aligned (independently of the position of the elements between cache lines). However, I don't know if that has an influence at all but I can guess that yes, it does. Furthermore, I want to use these SIMD instructions on my raw memory inside a kernel. It is an optimization detail of a kernel so I don't want to allocate e.g. __int128 instead of int.
All objects that you obtain "normally" are suitably aligned, i.e. aligned at alignof(T) (which need not be the same as sizeof(T). That includes dynamic arrays. (Typically, the allocator ::operator new will just return a maximally aligned address so as not to have to worry about how the memory is used.)
There are no cache lines in C++. This is a platform specific issue that you need to deal with yourself (but alignas may help).
Try alignas plus a static check if it works (since support for over-aligned types is platform dependent), otherwise just add manual padding. You don't really care whether your data is at the beginning of a cache line, only that no two data elements are on the same cache line.
It is worth stressing that alignment isn't actually a concept you can check directly in C++, since pointers are not numbers. They are convertible to numbers, but the conversion is not generally meaningful other than being reversible. You need something like std::align to actually say "I have aligned memory", or just use alignas on your types directly.

C++ Memory alignment in custom stack allocator

Usually data is aligned at power of two addresses depending on its size.
How should I align a struct or class with size of 20 bytes or another non-power-of-two size?
I'm creating a custom stack allocator so I guess that the compiler wont align data for me since I'm working with a continuous block of memory.
Some more context:
I have an Allocator class that uses malloc() to allocate a large amount of data.
Then I use void* allocate(U32 size_of_object) method to return the pointer that where I can store whether objects I need to store.
This way all objects are stored in the same region of memory and it will hopefully fit in the cache reducing cache misses.
C++11 has the alignof operator specifically for this purpose. Don't use any of the tricks mentioned in other posts, as they all have edge cases or may fail for certain compiler optimisations. The alignof operator is implemented by the compiler and knows the exact alignment being used.
See this description of c++11's new alignof operator
Although the compiler (or interpreter) normally allocates individual data items on aligned boundaries, data structures often have members with different alignment requirements. To maintain proper alignment the translator normally inserts additional unnamed data members so that each member is properly aligned. In addition the data structure as a whole may be padded with a final unnamed member. This allows each member of an array of structures to be properly aligned. http://en.wikipedia.org/wiki/Data_structure_alignment#Typical_alignment_of_C_structs_on_x86
This says that the compiler takes care of it for you, 99.9% of the time. As for how to force an object to align a specific way, that is compiler specific, and only works in certain circumstances.
MSVC: http://msdn.microsoft.com/en-us/library/83ythb65.aspx
__declspec(align(20))
struct S{ int a, b, c, d; };
//must be less than or equal to 20 bytes
GCC: http://gcc.gnu.org/onlinedocs/gcc-3.4.0/gcc/Type-Attributes.html
struct S{ int a, b, c, d; }
__attribute__ ((aligned (20)));
I don't know of a cross-platform way (including macros!) to do this, but there's probably neat macro somewhere.
Unless you want to access memory directly, or squeeze maximum data in a block of memory you don't worry about alignment -- the compiler takes case of that for you.
Due to the way processor data buses work, what you want to avoid is 'mis-aligned' access. Usually you can read a 32 bit value in a single access from addresses which are multiples of four; if you try to read it from an address that's not such a multiple, the CPU may have to grab it in two or more pieces. So if you're really worrying about things at this level of detail, what you need to be concerned about is not so much the overall struct, as the pieces within it. You'll find that compilers will frequently pad out structures with dummy bytes to ensure aligned access, unless you specifically force them not to with a pragma.
Since you've now added that you actually want to write your own allocator, the answer is straight-forward: Simply ensure that your allocator returns a pointer whose value is a multiple of the requested size. The object's size itself will already come suitably adjusted (via internal padding) so that all member objects themselves are properly aligned, so if you request sizeof(T) bytes, all your allocator needs to do is to return a pointer whose value is divisible by sizeof(T).
If your object does indeed have size 20 (as reported by sizeof), then you have nothing further to worry about. (On a 64-bit platform, the object would probably be padded to 24 bytes.)
Update: In fact, as I only now came to realize, strictly speaking you only need to ensure that the pointer is aligned, recursively, for the largest member of your type. That may be more efficient, but aligning to the size of the entire type is definitely not getting it wrong.
How should I align a struct or class with size of 20 bytes or another non-power-of-two size?
Alignment is CPU-specific, so there is no answer to this question without, at least, knowing the target CPU.
Generally speaking, alignment isn't something that you have to worry about; your compiler will have the rules implemented for you. It does come up once in a while, like when writing an allocator. The classic solution is discussed in The C Programming Language (K&R): use the worst possible alignment. malloc does this, although it's phrased as, "the pointer returned if the allocation succeeds shall be suitably aligned so that it may be assigned to a pointer to any type of object."
The way to do that is to use a union (the elements of a union are all allocated at the union's base address, and the union must therefore be aligned in such a way that each element could exist at that address; i.e., the union's alignment will be the same as the alignment of the element with the strictest rules):
typedef Align long;
union header {
// the inner struct has the important bookeeping info
struct {
unsigned size;
header* next;
} s;
// the align member only exists to make sure header_t's are always allocated
// using the alignment of a long, which is probably the worst alignment
// for the target architecture ("worst" == "strictest," something that meets
// the worst alignment will also meet all better alignment requirements)
Align align;
};
Memory is allocated by creating an array (using somthing like sbrk()) of headers large enough to satisfy the request, plus one additional header element that actually contains the bookkeeping information. If the array is called arry, the bookkeeping information is at arry[0], while the pointer returned points at arry[1] (the next element is meant for walking the free list).
This works, but can lead to wasted space ("In Sun's HotSpot JVM, object storage is aligned to the nearest 64-bit boundary"). I'm aware of a better approach that tries to get a type-specific alignment instead of "the alignment that will work for anything."
Compilers also often have compiler-specific commands. They aren't standard, and they require that you know the correct alignment requirements for the types in question. I would avoid them.

What is the byte alignment of the elements in a std::vector<char>?

I'm hoping that the elements are 1 byte aligned and similarly that a std::vector<int> is 4 byte aligned ( or whatever size int happens to be on a particular platform ).
Does anyone know how standard library containers get aligned?
The elements of the container have at least the alignment required for them in that implementation: if int is 4-aligned in your implementation, then each element of a vector<int> is an int and therefore is 4-aligned. I say "if" because there's a difference between size and alignment requirements - just because int has size 4 doesn't necessarily mean that it must be 4-aligned, as far as the standard is concerned. It's very common, though, since int is usually the word size of the machine, and most machines have advantages for memory access on word boundaries. So it makes sense to align int even if it's not strictly necessary. On x86, for example, you can do unaligned word-sized memory access, but it's slower than aligned. On ARM unaligned word operations are not allowed, and typically crash.
vector guarantees contiguous storage, so there won't be any "padding" in between the first and second element of a vector<char>, if that's what you're concerned about. The specific requirement for std::vector is that for 0 < n < vec.size(), &vec[n] == &vec[0] + n.
[Edit: this bit is now irrelevant, the questioner has disambiguated: The container itself will usually have whatever alignment is required for a pointer, regardless of what the value_type is. That's because the vector itself would not normally incorporate any elements, but will have a pointer to some dynamically-allocated memory with the elements in that. This isn't explicitly required, but it's a predictable implementation detail.]
Every object in C++ is 1-aligned, the only things that aren't are bitfields, and the elements of the borderline-crazy special case that is vector<bool>. So you can rest assured that your hope for std::vector<char> is well-founded. Both the vector and its first element will probably also be 4-aligned ;-)
As for how they get aligned - the same way anything in C++ gets aligned. When memory is allocated from the heap, it is required to be aligned sufficiently for any object that can fit into the allocation. When objects are placed on the stack, the compiler is responsible for designing the stack layout. The calling convention will specify the alignment of the stack pointer on function entry, then the compiler knows the size and alignment requirement of each object it lays down, so it knows whether the stack needs any padding to bring the next object to the correct alignment.
I'm hoping that the elements are 1 byte aligned and similarly that a std::vector is 4 byte aligned ( or whatever size int happens to be on a particular platform ).
To put it simply, std::vector is a wrapper for a C array. The elements of the vector are aligned as if they were in the array: elements are guaranteed to occupy continues memory block without any added gaps/etc, so that std::vector<N> v can be accessed as a C array using the &v[0]. (Why vector has to reallocate storage sometimes when elements are added to it.)
Does anyone know how standard library containers get aligned?
Alignment of elements is platform specific but generally a simple variable is aligned so that its address is divisible by its size (natural alignment). Structures/etc are padded (empty filler space at the end) on the largest data type they contain to ensure that if the structure is put into an array, all fields would retain their natural alignment.
For other containers (like std::list or std::map) use data via template mechanics are made a part of internal structure and the structure is allocated by operator new. The new is guaranteed (custom implementation must obey the rule too; inherited from the malloc()) to return memory block which is aligned on largest available primitive data type (*). That is to ensure that regardless what structure or variable would be places in the memory block, it will be accessed in aligned fashion. Unlike std::vector, obviously, the elements of most other STL containers are not guaranteed to be within the same continuous memory block: they are newed one by one, not with new[].
(*) As per C++ standard, "The allocation function (basic.stc.dynamic.allocation) called by a new-expression (expr.new) to allocate size bytes of storage suitably aligned to represent any object of that size." That is a softer requirement compared to one malloc() generally abides, as per POSIX: "The pointer returned if the allocation succeeds shall be suitably aligned so that it may be assigned to a pointer to any type of object [...]". C++ requirement in a way reenforces the natural alignment requirement: dynamically allocated char would be aligned as char requires, but not more.
Do you mean the vector members, or the vector structure itself? Members are guaranteed to be contiguous in memory but structure alignment is platform/compiler-dependent. On Windows this can be set at compile-time and also overridden using #pragma pack().
The answer for other containers is likely not the same as for vector, so I would ask specific questions about the ones you care about.
The alignment of the whole container is implementation dependent. It is usually at least sizeof(void*), that is 4 or 8 bytes depending on the platform, but may be larger.
If special (guaranteed) alignment is needed use plain arrays or write/adapt some generic array class with:
// allocation
char* pointer = _mm_malloc(size, alignment);
// deallocation
_mm_free(pointer);