std::tuple sizeof,是错过了优化吗?

Posted

技术标签:

【中文标题】std::tuple sizeof,是错过了优化吗?【英文标题】:std::tuple sizeof, is it a missed optimization? 【发布时间】:2020-01-06 08:55:40 【问题描述】:

我检查了所有主要的编译器,sizeof(std::tuple<int, char, int, char>) 对它们来说都是 16。大概他们只是将元素按顺序放入元组中,因此由于对齐而浪费了一些空间。

如果元组内部存储的元素如:int, int, char, char,那么它的 sizeof 可能是 12。

实现是否有可能做到这一点,还是被标准中的某些规则禁止?

【问题讨论】:

评论不用于扩展讨论;这个对话是moved to chat。 相关:Is there a GCC keyword to allow structure-reordering?、Can a C++ compiler re-order elements in a struct、Why doesn't GCC optimize structs?、Automated field re-ordering in C structs to avoid padding @phuclv:structtuple 之间有很大区别 => 一个是语言结构,另一个是库类型。你为什么认为他们必须遵守同样的规则? @MatthieuM。我在哪里说过他们遵守相同的规则? @phuclv:那么相关问题的意义何在?如果它们遵循不同的规则,那么查看 struct 的规则也无济于事。 【参考方案1】:

std::tuple sizeof,是不是错过了优化?

是的。

实现是否有可能做到这一点[?]

是的。

[是否]标准中的某些规则禁止它?

不!

通读[tuple],没有限制实现以模板参数顺序存储成员。

事实上,我能找到的每一段似乎都竭尽全力避免提及成员声明顺序:get<N>() 用于操作语义的描述。其他措辞是用“元素”而不是“成员”来表述的,这似乎是一个经过深思熟虑的抽象。

事实上,some implementations do apparently store the members in reverse order 至少可能仅仅是因为他们使用继承递归解压模板参数的方式(并且因为如上所述,他们被允许这样做)。

不过,具体谈谈您的假设优化,我不知道有任何实现不将元素存储在用户给定顺序的 [一些微不足道的功能] 中;我猜想提出这样的命令并为std::get 提供机器将是“困难的”,至少与您从中获得的收益相比是这样。如果你真的关心填充,你当然可以仔细选择你的元素顺序以避免它(在某些给定的平台上),就像你对一个类一样(不深入研究“打包”属性的世界)。 (“打包”元组可能是一个有趣的提议……)

【讨论】:

评论不用于扩展讨论;这个对话是moved to chat。【参考方案2】:

是的,这是可能的,并且已经(大部分)由R. Martinho Fernandes 完成。他曾经有一个名为Flaming Danger Zone的博客,现在由于某种原因关闭了,但它是sources are still available on github。

以下是 Size Matters 系列关于这个确切主题的全部四个部分:1、2、3、4。

您可能希望原始查看它们,因为 github 不理解所使用的 C++ 突出显示标记并将代码 sn-ps 呈现为不可读的单行。

他本质上是通过 C++11 模板元程序计算元组索引的排列,按非升序排列对元素进行排序,根据它存储元素,然后在每次访问时将其应用于索引。

【讨论】:

谢谢,我去看看。更好的方法是按对齐方式(而不是大小)进行排序。 @geza 我的错,他实际上是按对齐方式排序的。 请注意,这并没有说明是否允许标准tuple 以这种方式工作。所以,虽然很有趣,但并不能真正回答问题 该站点已启动并“运行”,但它似乎已被运行网络钓鱼攻击的域抢注者接管。告诉我,如果我告诉他们我的谷歌密码或其他东西,我就赢得了 100 台平板电脑中的 1 台。【参考方案3】:

他们可以。他们不这样做的一个可能原因是:一些架构,包括 x86,有一种索引模式,可以寻址 base + size × index 中的地址一条指令——但仅当 size 是 2 的幂时。或者执行与 16 字节边界对齐的加载或存储可能会稍微快一些。如果添加四个填充字节,这可以使寻址 std::tuple 数组的代码稍微更快、更紧凑。

【讨论】:

以上是关于std::tuple sizeof,是错过了优化吗?的主要内容,如果未能解决你的问题,请参考以下文章

只有两个成员的 std::pair 和 std::tuple 之间的区别?

另一个线程可以通过其地址访问本地函数\这个优化是不是有效\我错过了啥大事吗?

C++ 中的 std::pair 和 std::tuple

C++ 中的 std::pair 和 std::tuple

std::tuple

在函数调用时从异构初始化列表构建元组