是否需要明确的对齐?

时间:2014-08-13 15:43:23

标签: c++ memory alignment padding

经过一些阅读后,我了解编译器已经对结构或类进行了填充,以便可以在其自然对齐的边界上访问每个成员。那么在什么情况下编码人员需要明确调整以获得更好的性能?我的问题来自于此:

Intel 64和IA-32 Architechtures Optimization Reference:

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.

假设我有一个结构:

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

通过创建A类型的数组,即使我什么都不做,它也是正确对齐的。那么遵循指南并使对齐更强的要点是什么?

是否因为缓存线分裂?假设缓存行是64字节。在数组中第6次访问对象时,字节从61开始到72,这会减慢程序的速度?

顺便说一句,标准库中是否有一个宏通过返回std :: size_t的值告诉我基于运行机器的对齐要求?

4 个答案:

答案 0 :(得分:2)

让我直接回答你的问题:不,没有必要在C ++中明确地对齐数据以提高性能。

任何体面的编译器都会正确对齐底层系统的数据。

如果你有:

,问题就会出现(上面的变化)
 struct 
 {
     int w ;
     char x ;
     int y ;
     char z ;
 } 

这说明了两种常见的结构对齐问题。

(1)编译器很可能在x和z之后插入(2)3个对齐字节。如果x之后没有填充,则y未对齐。如果z之后没有填充,则w和x将在数组中未对齐。

您在手册中阅读的说明是针对汇编语言程序员和编译器编写者的。

当数据未对齐时,在某些系统(非英特尔)上会导致异常,而在其他系统上则需要多个处理器周期才能获取和写入数据。

答案 1 :(得分:1)

当你想要显式对齐时,我唯一可以解决的问题是你在结构之间直接复制/转换数据到char *以便在某种类型的二进制协议中进行序列化。

此处,意外填充可能会导致协议的远程用户出现问题。

在伪代码中:

struct Data PACKED
{
  char code[3];
  int val;
};

Data data = { "AB", 24 };
char buf[20];
memcpy(buf, data, sizeof(data));
send (buf, sizeof(data);

现在,如果我们的协议需要3个八位字节的代码,然后是val的4个八位字节整数值,那么如果我们使用上面的代码,我们将遇到问题。因为填充会给我们带来问题。让它工作的唯一方法是打包上面的结构(allignment 1)

答案 2 :(得分:1)

语言中确实存在一种设施(它不是宏,并且它不是来自标准库),无法告诉您对象或类型的对齐方式。它是alignof(另见:std::alignment_of)。

回答你的问题:一般来说,你不应该关心对齐。编译器会为你处理它,一般情况下/大多数情况下,它比你如何调整数据要好得多。

你需要摆弄对齐的唯一情况(参见alignas specifier)就是当你编写一些代码时,它允许一些可能不那么对齐的数据类型作为一些可能更对齐的数据的后备存储类型。

在幕后执行此操作的示例包括std::experimental::optionalboost::variant。标准库中还有明确的工具用于创建这样的后备存储,即std::aligned_storagestd::aligned_union

答案 3 :(得分:1)

  

通过创建A类型的数组,即使我什么都不做,它也是正确对齐的。那么遵循指南并使对齐更强的重点是什么?

ABI仅描述了如何使用它定义的数据元素。该指南不适用于您的struct

  

是否因为缓存线分裂?假设缓存行是64字节。在数组中第6次访问对象时,字节从61开始到72,这会减慢程序的速度?

缓存问题可以采用任何一种方式。如果您的算法随机访问数组并触及所有abc,则整个结构与16字节边界的对齐将提高性能,因为获取任何{来自内存的{1}},ab总是会获取另外两个。但是,如果仅使用线性访问或随机访问仅触摸其中一个成员,则16字节对齐会浪费缓存容量和内存带宽,从而降低性能。

彻底分析并不是必需的。您可以尝试查看alignas对性能的影响。 (或者添加一个虚拟成员,预先C ++ 11。)

  顺便说一句,标准库中是否有一个宏通过返回c的值来告诉我基于正在运行的机器的对齐要求?

C ++ 11(和C11)有一个alignof运算符。

相关问题