1

昨晚我在这个类上工作,作为内存对齐对象的类型安全包装器。我有字节数组和数学来访问字节数组的内存以读取和写入T. 不过,我很好奇,如何才能最有效地访问对齐的T.

我尝试使用一个公共T &调用Value,我将其初始化为T构造函数初始化列表中的对齐。像这样:

template <typename T, size_t alignment = 64>
struct Aligned {
private:
    std::uint8_t bytes[sizeof(T) + alignment - 1];
public:
    T & Value;
    Aligned(T const & value = T()) : Value(*reinterpret_cast<T *>((intptr_t)bytes + (alignment - 1) & ~intptr_t(alignment - 1))) {
        Value = value;
    }
};

这增加了类的大小,sizeof(T *)因为T & Value需要存储对齐的地址T

我的另一种方法是不存储地址,而是在每次需要访问时通过访问器方法计算它......

#include <array>
#include <cstdint>

template <typename T, size_t alignment = 64>
struct Aligned {
private:
    std::array<uint8_t, sizeof(T) + alignment - 1> const bytes;
public:
    T const & value() const {
        return *reinterpret_cast<T *>((intptr_t)bytes.data() + (alignment - 1) & ~intptr_t(alignment - 1));
    }
    void value(T const & x) {
        *reinterpret_cast<T *>((intptr_t)bytes.data() + (alignment - 1) & ~intptr_t(alignment - 1)) = x;
    }
    Aligned(T const & x = T()) {
        value(x);
    }
};

这种方法将需要指针算术和指针解引用(我认为?)每次访问但不会增加类的大小。

有没有其他方法或技巧来获得这两个优势?

4

2 回答 2

2

如果您有权访问 C++11,则可以使用新的 alignas 关键字让编译器为您对齐类型或变量。

alignas(64) classA myA;
于 2013-06-07T17:07:56.917 回答
1

我认为选项 1 看起来更整洁,我认为选项 2 没有任何好处。

但是,如果您需要知道哪个可以提供最佳性能,那么您确实需要以可以衡量性能的方式运行代码。我或其他任何人看着代码并说“A 看起来比 B 更好”是不好的——编译器不是 100% 可预测的,有时“看起来不错”的选择并不是最佳选择。这是我对所有绩效帖子所说的话,这是有充分理由的。我亲身经历过,您查看两段代码时说“嗯,它们将花费相同的时间,它们几乎相同”,但是由于存在一些细微的差异,因此 A 的性能明显优于 A情况 B(或相反)。

确保您不只是在这里测试微不足道的情况,您需要一些不同的变体,例如具有相当数量成员的结构、大小数组以及简单int的 , long long,double等。

于 2013-06-07T16:51:53.960 回答