【发布时间】:2016-01-08 07:28:46
【问题描述】:
我有一个来自模板参数的 4 个类型字段的结构:
template <typename T1, typename T2, typename T3, typename T4>
struct __attribute__((aligned(8))) four_tuple {
typedef struct {
T1 t1;
T2 t2;
T3 t3;
T4 t4;
} payload;
payload p;
};
T1、T2、T3 和 T4 的每个类型都保证是原始类型或 four_tuple<...>::payload 类型。保证是递归的 - 您可以将结构视为对叶节点为原始类型的 quadtree 进行编码。
我的目标是使结构具有最小可能的sizeof,条件是所有叶节点都正确对齐。允许优化的工具是类模板特化,使用:
- 重新排序字段
t1、t2、t3、t4 - 添加填充字段
-
payload上的 gcc 属性packed - 也许是其他人?
我觉得使用enable_if 和 SFINAE 可以巧妙地解决这个问题。有人能找到吗?
为了说明问题,如果我们按原样使用上述实现using Foo = four_tuple<char,double,char,double>,我们将有一个 32 的大小用于有效负载和整体。如果我们简单地声明有效载荷packed,double 将不会很好地对齐。以降序对字段重新排序的模板专业化(此处为double, double, char, char)将提供有效负载和总大小为 24。但它使用的额外 6 个字节是浪费的,从考虑using Bar = four_tuple<Foo::payload,int,int,int> 可以看出。使用最佳包装Bar 可以容纳 32 个字节,但使用此方案需要 40 个。直言不讳地使用packed 应用字段重新排序将导致Bar 中的int 未对齐 - 需要一些填充符。
我知道,由于缓存考虑,通常重组结构字段的内存布局可能会影响性能,并且通常这些影响至少与更好打包的任何潜在收益一样重要。不过,我想探索权衡取舍,如果不解决这个问题,我真的无法在我的上下文中正确地做到这一点。
【问题讨论】:
-
我没看到。如果按照您描述的方式重新排序,但不添加
packed,有什么问题?在另一种类型中使用它不会产生任何未对齐的字段,因为编译器已经使用填充来修复它。 -
顺便说一句,为什么要强制对齐结构?如果你的类型是四个
chars,你想要一个 4 的大小,不是吗?这不能要求对齐 8。 -
@hvd
four_tuple<Foo::payload,int,int,int>如果包装得当,可以达到 32 的大小而不会出现错位。如果你不添加packed,它将有40的大小。 -
@hvd 解决我的问题只保证叶子将相对于
four_tuple对齐。如果four_tuple的特定实例未对齐,则所有赌注都将取消。这就是我对齐 8 的原因。 -
stackoverflow.com/questions/18975130/… 详细讨论了编译时重新排序以优化打包。答案也参考rmf.io/cxx11/optimal-tuple-i 讨论元组数据布局。
标签: c++ c++11 memory-alignment packed