2

我正在使用 x86 英特尔机器和 Windows 7,以及 Visual C++(版本 2005/2012 express)

我一直在玩对齐(我只是将其作为学习练习。)当然,我理解填充方面对类/结构大小的影响。我相信我理解由于 CPU 指令的工作方式和期望数据的方式,它也可以更好地对齐。

我一直在查看许多不同的资源,例如(有趣的) c++ 数据对齐/成员顺序和继承 (以及其他链接,如维基百科)http://en.wikipedia.org/wiki/Data_structure_alignment

可能会受到影响的一个领域(我读过)似乎是性能,因为数据需要为寄存器的特定大小,未对齐的数据可能会导致问题(参见维基百科)。

我编写了一些代码,在其中创建了 3 个结构,所有结构都具有相同的成员,打包设置为 1 ,正常对齐,并且重新排列了成员。这给了我大小为 8、10 和 12 的对象。我为每个对象运行了类似于以下的代码:

struct MixedData1
{
    char Data1;
    short Data2;
    int Data3;
    char Data4;

    void operator() (MixedData1& md)
    {
        md.Data1 = 'a';
        md.Data2 = 1024;
        md.Data3 = 1000000;
        md.Data4 = 'b';
    }
};

typedef std::vector<MixedData1> MDVector;


int main(int argc, char* argv[])
{
    MixedData1 md;
    for(int count = 0; count < 10 ; count++)
    {    
        {
        std::cout << sizeof(md) << std::endl;
        boost::timer::auto_cpu_timer t;
        MDVector mdv(10000000); 
        std::fill(mdv.begin(),mdv.end(),md );
        std::for_each(mdv.begin(),mdv.end(),md);
        }
    }
}

我对这些值并不感兴趣,因此向量中的每个元素都被初始化为相同的。无论如何,我得到的结果表明运行时间随着结构的大小而增加 - IE with pack(1) (8 bytes) 我得到了最快的 0.08s,而正常对齐 (12 bytes) 我得到了最慢的 0.105 。

我的问题是关于错误对齐的影响。在我作为 C++ 程序员的X年里,我认为我从来没有遇到过任何对齐问题,但当然它可能只是让我过去了。

(1)对齐在我的测试(编辑)中产生了影响(我相信),但是正如尼尔发布的那样,这只是由于 struct size 的差异。我尝试按照他的回复访问该成员,但我在那里没有看到任何实际效果....有更清晰的例子吗?有没有办法让我看到错位的巨大影响?(2)如果可能的话,有没有办法引起由错位引起的碰撞。

4

2 回答 2

4

您的代码所做的只是测试处理器复制内存的速度。内存越大,复制越慢。结构内各个成员的对齐方式与复制速度无关,只有结构的大小很重要。

如果要查看对齐的效果,则需要编写实际访问各个未对齐结构成员的代码。例如,您可以编写一个循环来增加每个结构的 data3 成员。根据架构的不同,编译器可能会意识到它必须使用不同的指令来执行算术;在 x86 上通常不是这种情况,编译器会发出看起来很自然的代码,因为处理器能够处理未对齐的访问。一些处理器实际上可以以与对齐数据相同的速度读取和写入未对齐数据。一个简单的例子是 8088,因为它只有一个 8 位数据总线,所以无论如何所有 16 位指令都是使用两个负载来模拟的,

如果你想通过错位引发崩溃,那么通常你需要在不同类型之间转换指针。然后编译器可能并不总是意识到您的指针可能未对齐,并且不会为未对齐的访问生成正确的指令。例如,您可以尝试在 cast char* 指针上调用 SSE 指令。

于 2012-11-04T22:07:32.740 回答
1

简短的回答:在实践中并不重要。

原因如下:1 或 2 次缓存未命中可能需要不到一毫秒的时间,因此只有在以下情况下访问未对齐的数据才会成为问题:

  1. 数据跨越两条缓存线
  2. 您访问了许多未对齐的数据,这些数据在内存中并不连续。

由于 2. 无论如何都会产生大量缓存未命中,因此即使数据对齐,您也不应该处于这种情况。改进对齐方式可以将缓存未命中的数量提高不超过 2 倍,但连续存储数据可以将性能提高很多倍。

有一些指令需要对齐数据。如果您需要这些说明,您要么知道它,要么您的编译器应该为您确保对齐。这是否会影响性能取决于您的处理器的微架构和编译器。无论如何,您应该首先分析您的程序以找到瓶颈。如果对齐显着影响程序的性能,请修复它。否则不要担心。

于 2012-11-05T18:33:02.717 回答