数据(错误)对齐的影响

时间:2012-11-04 21:32:07

标签: c++ visual-studio alignment

我正在使用x86 intel机器,Windows 7,以及Visual C ++(版本2005/2012快递)

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

我一直在寻找许多不同的资源,例如(有趣的) c++ data alignment /member order & inheritance (以及维基百科等其他链接)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);
        }
    }
}

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

我的问题是关于错误对齐的影响。我不认为我作为一名C ++程序员在整个 X 年期间遇到任何问题,但当然它可能只是让我过去了。

(1)对齐在我的测试(编辑)中产生影响(我相信),但是Neil发布它只是由于结构大小的差异。我尝试按照他的回复访问该成员,但我看到没有真正的效果....是否有更清晰的例子?有没有办法可以看到错位的戏剧效果? (2)如果可能的话,是否有办法引起由不对中引起的碰撞。

2 个答案:

答案 0 :(得分:4)

您的所有代码都是测试以查看处理器复制内存的速度。内存越多,副本越慢。结构中各个成员的对齐与复制的速度无关,只有结构的大小才重要。

如果要查看对齐的效果,则需要编写实际访问单个未对齐结构成员的代码。例如,您可以编写一个循环来增加每个结构的data3成员。根据体系结构,编译器可能意识到它必须使用不同的指令来执行算术;在x86上通常不是这种情况,编译器会发出自然的代码,因为处理器能够处理未对齐的访问。某些处理器实际上可以以与对齐数据相同的速度读取和写入未对齐数据。一个简单的例子是8088,因为它只有一个8位数据总线所以所有16位指令都是使用两个负载模拟的,但是最新的处理器大部分时间都是从缓存线读取的,因此唯一的时间是未对齐的数据可能会产生影响,当数据穿过缓存行时。

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

答案 1 :(得分:1)

简短的回答:在实践中没关系。

原因如下:1或2个缓存未命中可能需要不到1毫秒,因此访问未对齐数据只会出现问题:

  1. 数据横跨两个缓存行
  2. 您可以访问许多未对齐的数据,这些数据在内存中不是连续的。
  3. 因为2.无论如何都会产生大量的缓存未命中,即使数据是对齐的,也不应该处于这种情况。改进对齐可以将缓存未命中数减少不超过2倍,但连续存储数据可以多次提高性能。

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