访问对齐T& S的最有效方法是什么?来自char []?

时间:2013-06-07 16:25:18

标签: c++ templates memory-alignment false-sharing

我昨晚在这个类上工作,作为内存对齐对象的类型安全包装器。我有字节数组和数学来访问字节数组的内存,以便以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);
    }
};

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

是否有任何其他方法或技巧可以获得这两种优势?

2 个答案:

答案 0 :(得分:2)

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

alignas(64) classA myA;

答案 1 :(得分:1)

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

但是,如果您需要知道哪种方式可以提供最佳性能,那么您确实需要以可以衡量性能的方式运行代码。我或其他任何人,看着代码并说“A看起来比B好”并不好 - 编译器不是100%可预测的,有时选择“看起来不错”并不是最好的选择。这是我对所有表现帖子的看法,这是有充分理由的。我个人经历过这个,你看两段代码,说“好吧,它们会花费相同的时间,它们几乎是相同的”,但是因为有一些细微的差别,在A的情况下性能明显好于如果是B(或其他方式)。

请确保您不仅仅在这里测试一些简单的案例,您需要一些不同的变体,例如具有相当数量的成员,大型和小型数组的结构,以及简单的intlong longdouble

相关问题