4

我相信我会的。由于对齐,矩阵库 Eigen3 可能比我自己的任何矩阵实现都快得多。

我最近开始研究使用 C++ 进行对齐。我偶然发现了 alignas 和 alignof 函数,并决定做一些测试。

我的第一个发现是结构的成员会自动对齐。我们以下面的结构为例:

struct MyStruct
{
    char m_c; // 1 byte
    double m_x; // 8 bytes
};

并与这个比较:

struct MyAlignedStruct
{
    char m_c; // 1 byte
    alignas(8) double m_x; // 8 bytes
};

我使用 alignas 而不是添加填充成员(char [7]),根据我的理解,这是等效的。

现在,两个结构的内存查看器显示如下:

62 00 00 00 8e a8 79 35 00 00 00 00 00 00 10 40 // MyStruct
62 ff ff ff 24 00 00 00 00 00 00 00 00 00 10 40 // MyAlignedStruct

第一个字节对应一个 char ('b')。使用 Mystruct 时,接下来的 7 个字节用something填充,最后 8 个字节代表双精度。使用 MyAlignedStruct 时,会发生非常相似的情况。sizeof() 函数为两个结构返回 16 个字节(我预计 MyStruct 为 9 个字节)。

所以我的第一个问题来了:如果编译器自己对齐,为什么我需要对齐?

我的第二个发现是 alignas(..) 并没有加快我的程序。我的实验如下。想象一下以下简单的结构:

struct Point
{
    double m_x, m_y, m_z;
};

如果我用该结构的实例填充一个向量,并假设第一个实例是 32 字节对齐的,那么每个结构将占用 24 个字节,并且字节序列将不再是 32 字节对齐的。老实说,我不确定如何通过对齐来提高速度,否则,我很可能不会在这里写。尽管如此,我还是使用了 alignas 来获得以下结构:

alignas(32) struct Point
{
    double m_x, m_y, m_z;
};

现在,Point 的连续实例将从 32 字节的倍数开始。我测试了这两个版本:在用结构实例填充一个巨大的向量后,我将所有双精度数相加并记录时间。我发现 32 字节对齐的结构和另一个之间没有区别。

所以我的第二个问题与我的第一个问题相同:为什么我需要对齐?

4

1 回答 1

3

如果编译器自行对齐,为什么我需要 alignas?

有几个原因让我不由自主地想到:

  1. 编译器可能被配置为打包结构,如下所述:

    强制 C++ 结构紧密打包

    但是您希望某些特定结构具有对齐的成员

  2. 您想要超出类型要求的对齐方式,例如

    alignas(1024) struct MyStruct
    {
        char m_c; // 1 byte
        alignas(32) double m_x; // 8 bytes
    };
    

    这可能是由于硬件限制,例如您有一张可以从内存中以 1024 页分辨率抓取内容的卡;然后,在该卡上,以 32 字节为单位进行数据访问。该示例将满足这些要求,而不必插入虚拟字段。

  3. 键入 punning/slicing:您可能会获得以下数组的地址:

    struct s1
    {
        char m_c;
        uint32_t m_d;
        char m_e;
    };
    

    但我实际上使用的是

    struct s2
    {
        char m_c;
        mystery_type_with_size_64_bits m_d;
        char m_e;
    };
    

    因此,即使您想以 . 身份工作m_duint32_t但您也需要做m_e对。

于 2018-03-15T15:06:08.143 回答