Is explicit alignment required?

After some readings, I understand that the compiler has done padding for structures or classes, so that each member can be accessed at its natural aligned border. So, under what circumstances is it necessary for encoders to do clear alignment to achieve better performance? My question arises here:

Intel 64 and IA-32 Archiving Optimization Reference Guide:

For best performance, align data as follows: Align 8-bit data at any address. Align 16-bit data to be contained within an aligned 4-byte word. Align 32-bit data so that its base address is a multiple of four. Align 64-bit data so that its base address is a multiple of eight. Align 80-bit data so that its base address is a multiple of sixteen. Align 128-bit data so that its base address is a multiple of sixteen. 

So, suppose I have a structure:

 struct A { int a; int b; int c; } // size = 12; // aligned on boundary of: 4 

By creating an array of type A, even if I do nothing, it will be aligned correctly. Then what's the point of following the manual and making alignment stronger?

Is it because of line splitting in cache? Assuming the cache line is 64 bytes. At the 6th access of the object in the byte array, it starts from 61 to 72, which slows down the program

BTW, is there a macro in the standard library that tells me the alignment requirement based on the current machine, returning the value std :: size_t?

+6
source share
4 answers

Let me answer your question directly: No, there is no need to explicitly align data in C ++ for performance.

Any decent compiler will correctly align the data for the base system.

A problem would occur (change above) if you had:

  struct { int w ; char x ; int y ; char z ; } 

This illustrates two problems of aligning the overall structure.

(1) Most likely, the compiler will insert (2) 3 bytes of alignment after x and z. If there are no indents after x, y is not aligned. If after z there is no filling, w and x will be uneven in arrays.

The instructions that you read in the manual are aimed at assembler programmers and compiler authors.

When data is not aligned, on some systems (not Intel) this throws an exception, while on others it takes several processor cycles to extract and write data.

+2
source

The only time I want explicit alignment is that you directly copy / castrate data between your structure and char * for serialization in a binary protocol of a certain type.

Here, unexpected populations can cause problems with the remote user of your protocol.

In pseudo code:

 struct Data PACKED { char code[3]; int val; }; Data data = { "AB", 24 }; char buf[20]; memcpy(buf, data, sizeof(data)); send (buf, sizeof(data); 

Now, if our protocol expects 3 octets of code, followed by an integer of 4 octets for val, we will run into problems if we use the code above. Since the gasket will introduce problems for us. The only way to get this to work so that the structure above is packed (allignment 1)

+1
source

There really is a tool in the language (it's not a macro, not a standard library) to tell you about aligning an object or type. This is alignof (see also: std::alignment_of ).

To answer your question: in general, you do not have to worry about alignment. The compiler will take care of this for you, and in general / in most cases, it knows a lot, much better than you, to align your data.

The only time you need to bother with alignment (see alignas specifier ) is when you write code that allows some, possibly less aligned data type to be a support repository for some, possibly more aligned data type.

Examples of things that do this under the hood are std::experimental::optional and boost::variant . It also provides the means of a standard library for creating such a backup storage, namely std::aligned_storage and std::aligned_union .

+1
source

By creating an array of type A, even if I do nothing, it will be aligned correctly. Then what's the point of following the manual and making alignment stronger?

The ABI only describes how to use the data elements it defines. This guide does not apply to your struct .

Is it because of line splitting in cache? Assuming the cache line is 64 bytes. At the 6th access of the object in the byte array, it starts from 61 to 72, which slows down the program

The cache question can go anyway. If your algorithm randomly accesses an array and affects all a , b and c , then aligning the entire structure to a 16-byte boundary will improve performance, since fetching a , b , or c from memory will always extract the other two. However, if you are using only linear access or random access to only one of the participants, alignment of 16 bytes will direct to cache memory and memory bandwidth, reducing performance.

A comprehensive analysis is not really needed. You can just try and see what alignas for performance. (Or add a dummy element, pre-C ++ 11.)

BTW, is there a macro in the standard library that tells me the alignment requirement based on the current machine, returning the value std::size_t ?

C ++ 11 (and C11) have an alignof operator.

+1
source

Source: https://habr.com/ru/post/973772/


All Articles