- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
考虑这个代码:
#include <utility>
#include <tuple>
std::pair<int, int> f1()
{
return std::make_pair(0x111, 0x222);
}
std::tuple<int, int> f2()
{
return std::make_tuple(0x111, 0x222);
}
f1():
movabs rax,0x22200000111
ret
f2():
movabs rax,0x11100000222 ; opposite packing order, not important
ret
f2()
生成了不同的代码:
f2():
movabs rax,0x11100000222
mov QWORD PTR [rdi],rax
mov rax,rdi
ret
f2():
movabs rdx,0x11100000222
mov rax,rdi
mov QWORD PTR [rdi],rdx ; GCC 4-6 use 2 DWORD stores
ret
std::tuple
时生成的代码更糟适合单个寄存器,vs
std::pair
?这似乎特别奇怪,因为 Clang 3 和 4 似乎是最佳的,但 5 不是。
最佳答案
简短的回答是因为 libstc++
gcc
使用的标准库实现和 clang
在 Linux 上实现 std::tuple
具有非平凡的移动构造函数(特别是 _Tuple_impl
基类具有非平凡的移动构造函数)。另一方面, std::pair
的复制和移动构造函数都是默认的。
这反过来会导致从函数返回这些对象以及按值传递它们的调用约定中与 C++-ABI 相关的差异。
血腥细节
您在遵循 SysV x86-64 ABI 的 Linux 上运行测试。此 ABI 具有向函数传递或返回类或结构的特定规则,您可以阅读有关 here 的更多信息。 .我们感兴趣的具体案例是否是两个int
这些结构中的字段将获得 INTEGER
类或 MEMORY
类(class)。
recent ABI 规范的版本是这样说的:
The classification of aggregate (structures and arrays) and union types works as follows:
- If the size of an object is larger than eight eightbytes, or it contains un- aligned fields, it has class MEMORY 12 .
- If a C++ object has either a non-trivial copy constructor or a non-trivial destructor 13 , it is passed by invisible reference (the object is replaced in the parameter list by a pointer that has class INTEGER) 14 .
- If the size of the aggregate exceeds a single eightbyte, each is classified separately. Each eightbyte gets initialized to class NO_CLASS.
- Each field of an object is classified recursively so that always two fields are considered. The resulting class is calculated according to the classes of the fields in the eightbyte
gcc
被记录为遵循
does include move constructors :
If the parameter type is non-trivial for the purposes of calls, the caller must allocate space for a temporary and pass that temporary by reference. Specifically:
- Space is allocated by the caller in the usual manner for a temporary, typically on the stack.
A type is considered non-trivial for the purposes of calls if:
- it has a non-trivial copy constructor, move constructor, or destructor, or
- all of its copy and move constructors are deleted.
tuple
从 ABI 的角度来看,它不被认为是微不足道的可复制的,它会得到
MEMORY
处理,这意味着您的函数必须填充由
rdi
中的调用传入的堆栈分配对象。 .
std::pair
函数可以在
rax
中传回整个结构因为它适合一个
EIGHTBYTE
并有类(class)
INTEGER
.
tuple
来说效率较低因为这个 ABI 不同是“烘焙”的。
f1()
and f2()
functions and do some math on the result :
int add_pair() {
auto p = f1();
return p.first + p.second;
}
int add_tuple() {
auto t = f2();
return std::get<0>(t) + std::get<1>(t);
}
add_tuple
方法从一个劣势开始,因为它必须调用
f2()
这效率较低,它还必须在堆栈上创建一个临时元组对象,以便将其传递给
f2
作为隐藏参数。没关系,这两个函数都经过了全面优化,可以直接返回正确的值:
add_pair():
mov eax, 819
ret
add_tuple():
mov eax, 819
ret
tuple
将相对静音:它为必须符合 ABI 的函数增加了一个小的固定开销,但这仅在相对意义上对于非常小的函数真正重要 - 但这些函数很可能在它们可以被声明的地方被声明内联(或者如果没有,您将把性能放在桌面上)。
f1()
这样的代码。为
std::tuple
如果他们会破坏 ABI 兼容的调用者。
libc++
,您可以清楚地看到这一点。而不是 Linux 默认的
libstdc++
- 这个实现没有显式的移动构造函数(正如 Marc Glisse 在评论中提到的,为了向后兼容,他们坚持这个实现)。现在
clang
(大概是 gcc,虽然我没有尝试过),生成
same optimal code在这两种情况下:
f1(): # @f1()
movabs rax, 2345052143889
ret
f2(): # @f2()
movabs rax, 2345052143889
ret
clang
以不同的方式编译它?简直就是
a bug in clang或规范中的错误,取决于您如何看待它。在需要传递指向临时对象的隐藏指针的情况下,规范没有明确包含移动构造。不符合 IA-64 C++ ABI。例如,clang 过去使用的编译方式与
gcc
不兼容。或更新版本的
clang
.规范是
eventually updated和 clang
behavior changed in version 5.0 .
clang
在某些时候改变了他们的行为,这可能解释了这种转变:
The ABI specification for some argument passing cases involving move constructors were unclear, and when they were clarified, clang changed to follow the ABI. This is probably one of those cases.
关于c++ - 返回一个 2 元组是否比 std::pair 效率低?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46901697/
我的 Linux Centos Apache 服务器的性能有问题。我有一个程序(用 c 语言编写)可以同时执行许多 http 请求。这个过程本身看起来非常有效,就好像我可以同时向外部服务器发出 500
我想知道如何将并行端口上的数据引脚设置为高电平和低电平。我相信我可以使用 PyParallel 来实现此目的,但我不确定如何设置特定的引脚。 谢谢! 最佳答案 您在这里谈论的是软件-硬件接口(inte
让我有一个像这样的日期时间索引的数据框: date_time open high low close vol 2018-05-13 18:00:00 70.
在 emacs Octave 模式下,当我输入 M-x run-octave 时,命令会卡住,所以我使用 C-g 进行转义。我可以用 C-x b 切换到 *Inferior Octave* 缓冲区,但
我正在 sklearn 中运行 gridsearchCV,尝试使用此代码找到最佳模型参数。 modelDNN= KerasRegressor(build_fn=build_DNN_model, epo
美好的一天。我想知道 android 存储是否低,它会影响应用程序性能吗?因为同一个应用程序在另一台设备上运行速度很快,而同样的应用程序在另一台设备上非常滞后,后者有 12GB 内存中的 2GB 可用
所以我在列卡上有一个带有索引的表 当我运行时 SELECT COUNT(DISTINCT(card)) FROM table 它返回 490 个不同的条目 但是当我运行的时候 SHOW INDEXES
我正在使用手动方法将二进制转换为十进制。此代码在最后一位为高的情况下工作正常,例如:1001。当最后一位为零 [低] 时会出现错误。例如:1010 应该给出 10 但给出 5,因为没有考虑最后一位。有
我一直在努力优化我的站点和数据库,并且我一直在使用 mysqltuner.pl 来帮助解决这个问题。除了表缓存命中率,无论我在 my.cnf 中将它提高多高,我几乎都得到了正确的结果,我仍然命中大约
深入研究 sprite kit (xcode 5)。我正在使用两个示例程序,1. 创建新项目时包含的默认宇宙飞船示例和 2. 我下载的 Adventure Game。 在 iOS 模拟器中运行这些示例
编辑: 感谢大家在这里提供答案,项目已完成。 https://github.com/0xyg3n/ProcessDaemon/ 如果有人想出可能会更好的多线程解决方案,我想。 我是 C# 的新手,我想
我有一个交换 Word 变量的字节(低/高)的过程(它与 System.Swap 函数执行相同的操作)。该过程在编译器优化关闭时有效,但在编译器优化打开时无效。有人可以帮我解决这个问题吗? proce
我以前听说过这些术语描述语言,例如 C 并不是一种低级语言,C++是中级语言,而Python是一种高级语言。我知道它必须与代码的编译方式以及代码的编写方式有关。但是我想知道的是,什么将语言定义为这三类
我有一个关于 NoSQL 类型数据库的问题,特别是 MongoDB,但它通常适用于大多数键值或基于文档的存储。 NoSQL 的一些卖点是速度和可扩展性,但在我看来,与关系数据库相比,开销很大。 你有很
如果没有此代码,fps 为 60-65。但是当我使用这段代码时,fps 下降到 50。 另一个问题是某些设备上的 FPS 太低。然而,游戏非常简单。我对所有形状使用 ShapeRenderer。游戏在
您好,我的名字是 Ryan,我目前正在开发自己的 2D java 游戏。目前游戏世界中有很多物体。游戏重新开始时,世界会加载 100 棵随机放置的树木,这些树木是使用数组列表和树类制作的。我的游戏使用
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我刚刚将我的 Heroku postgres 数据库从 Kappa 计划(800MB RAM,postgres 9.1)升级到 Ronin 计划(1.7GB RAM,postgres 9.2),但性能
现在我正在使用我的 NSDictionary 并运行所有值的循环以找到低值、高值和计算平均值。 由于我是IOS 的新手,所以我想问问是否有更好的方法来做到这一点。有没有? 谢谢。 最佳答案 这个问题的
我目前正在使用 genuino 101 进行一个项目,我需要通过 i2c 读取大量数据,以填充任意大小的缓冲区。从下图中我可以看到读取请求本身只需要大约 3毫秒,写请求大约 200 纳秒。 但是在同一
我是一名优秀的程序员,十分优秀!