简体   繁体   中英

Is explicit alignment necessary?

After some readings, I understand that compiler has done the padding for structs or classes such that each member can be accessed on its natural aligned boundary. So under what circumstance is it necessary for coders to make explicit alignment to achieve better performance? My question arises from here:

Intel 64 and IA-32 Architechtures Optimization Reference Manual:

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 struct:

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 is properly aligned. Then what's the point to follow the guide and make the alignment stronger?

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

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

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

Any decent compiler will properly align the data for underlying system.

The problem would come (variation on above) if you had:

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

This illustrates the two common structure alignment problems.

(1) It is likely a compiler would insert (2) 3 alignment bytes after both x and z. If there is no padding after x, y is unaligned. If there is no padding after z, w and x will be unaligned in arrays.

The instructions are you are reading in the manual are targeted towards assembly language programmers and compiler writers.

When data is unaligned, on some systems (not Intel) it causes an exception and on others it take multiple processor cycles to fetch and write the data.

The only time I can thing of when you want explicit alignment is when you are directly copying/casting data between your struct to a char* for serialization in some type of binary protocol.

Here unexpected padding may cause problems with a remote user of your protocol.

In pseudocode:

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 a 4 octet integer value for val, we will run into problems if we use the above code. Since padding will introduce problems for us. The only way to get this to work is for the struct above to be packed (allignment 1)

There is indeed a facility in the language (it's not a macro, and it's not from the standard library) to tell you the alignment of an object or type. It's alignof (see also: std::alignment_of ).

To answer your question: In general you should not be concerned with alignment. The compiler will take care of it for you, and in general/most cases it knows much, much better than you do how to align your data.

The only case where you'd need to fiddle with alignment (see alignas specifier ) is when you're writing some code which allows some possibly less aligned data type to be the backing store for some possibly more aligned data type.

Examples of things that do this under the hood are std::experimental::optional and boost::variant . There's also facilities in the standard library explicitly for creating such a backing store, namely std::aligned_storage and std::aligned_union .

By creating an array of type A, even if I do nothing, it is properly aligned. Then what's the point to follow the guide and make the alignment stronger?

The ABI only describes how to use the data elements it defines. The guideline doesn't apply to your struct .

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

The cache question could go either way. If your algorithm randomly accesses the array and touches all of a , b , and c then alignment of the entire structure to a 16-byte boundary would improve performance, because fetching any of a , b , or c from memory would always fetch the other two. However if only linear access is used or random accesses only touch one of the members, 16-byte alignment would waste cache capacity and memory bandwidth, decreasing performance.

Exhaustive analysis isn't really necessary. You can just try and see what alignas does for performance. (Or add a dummy member, pre-C++11.)

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM