- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我决定要对特定函数进行基准测试,所以我天真地编写了这样的代码:
#include <ctime>
#include <iostream>
int SlowCalculation(int input) { ... }
int main() {
std::cout << "Benchmark running..." << std::endl;
std::clock_t start = std::clock();
int answer = SlowCalculation(42);
std::clock_t stop = std::clock();
double delta = (stop - start) * 1.0 / CLOCKS_PER_SEC;
std::cout << "Benchmark took " << delta << " seconds, and the answer was "
<< answer << '.' << std::endl;
return 0;
}
一位同事指出,我应该将 start
和 stop
变量声明为 volatile
以避免代码重新排序。例如,他建议优化器可以像这样有效地重新排序代码:
std::clock_t start = std::clock();
std::clock_t stop = std::clock();
int answer = SlowCalculation(42);
起初我怀疑这种极端的重新排序是否被允许,但经过一些研究和实验后,我了解到确实如此。
但 volatile 感觉不是正确的解决方案; volatile 不只是用于内存映射 I/O 吗?
尽管如此,我添加了 volatile
并发现基准测试不仅耗时明显更长,而且每次运行都非常不一致。如果没有 volatile(并且幸运地确保代码没有被重新排序),基准测试始终需要 600-700 毫秒。使用 volatile,通常需要 1200 毫秒,有时甚至超过 5000 毫秒。两个版本的反汇编列表显示除了寄存器选择不同之外几乎没有区别。这让我想知道是否有另一种方法可以避免代码重新排序而不会产生如此巨大的副作用。
我的问题是:
What is the best way to prevent code reordering in benchmarking code like this?
我的问题类似于 this one (这是关于使用 volatile 来避免省略而不是重新排序),this one (没有回答如何防止重新排序)和this one (争论问题是代码重新排序还是死代码消除)。虽然这三个人都在这个确切的主题上,但没有人真正回答我的问题。
更新:答案似乎是我的同事弄错了,这样的重新排序不符合标准。我支持所有这么说的人,并将赏金授予马克西姆。
我见过一种情况(基于 this question 中的代码),其中 Visual Studio 2010 按照我的说明重新排序了时钟调用(仅在 64 位版本中)。我正在尝试做一个最小的案例来说明这一点,以便我可以在 Microsoft Connect 上提交错误。
对于那些说 volatile 应该慢得多的人,因为它强制读取和写入内存,这与发出的代码不太一致。在我对 this question 的回答中,我展示了带有和不带有 volatile 的代码的反汇编。在循环内部,所有内容都保存在寄存器中。唯一的显着差异似乎是寄存器选择。我不太了解 x86 程序集,无法知道为什么非易失版本的性能始终快,而易失版本的性能不一致(有时甚至非常慢)。
最佳答案
A colleague pointed out that I should declare the start and stop variables as volatile to avoid code reordering.
对不起,你的同事错了。
编译器不会对定义在编译时不可用的函数的调用重新排序。简单地想象一下,如果编译器对诸如 fork
和 exec
之类的调用重新排序或围绕这些调用移动代码,将会产生怎样的欢笑。
换句话说,任何没有定义的函数都是编译时内存屏障,即编译器不会移动调用之前的后续语句或调用之后的先前语句。
在您的代码中,对 std::clock
的调用最终会调用一个定义不可用的函数。
我不能推荐足够的观看atomic Weapons: The C++ Memory Model and Modern Hardware因为它讨论了关于(编译时)内存屏障和 volatile
以及许多其他有用的东西的误解。
Nevertheless, I added volatile and found that not only did the benchmark take significantly longer, it also was wildly inconsistent from run to run. Without volatile (and getting lucky to ensure the code wasn't reordered), the benchmark consistently took 600-700 ms. With volatile, it often took 1200 ms and sometimes more than 5000 ms
不确定是否应该归咎于 volatile
。
报告的运行时间取决于基准测试的运行方式。确保禁用 CPU 频率缩放,以便它不会打开涡轮模式或在运行过程中切换频率。此外,微基准测试应作为实时优先级进程运行,以避免调度噪音。可能是在另一次运行期间,某些后台文件索引器开始与您的基准测试竞争 CPU 时间。见 this了解更多详情。
一个好的做法是测量执行函数多次所需的时间并报告 min/avg/median/max/stdev/total 时间数。高标准偏差可能表明没有进行上述准备工作。第一次运行通常是最长的,因为 CPU 缓存可能是冷的,它可能需要许多缓存未命中和页面错误,并且还会在第一次调用时解析来自共享库的动态符号(惰性符号解析是 Linux 上的默认运行时链接模式,例如),而后续调用将以更少的开销执行。
关于c++ - 基准测试、代码重新排序、 volatile ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15041519/
我尝试理解[c代码 -> 汇编]代码 void node::Check( data & _data1, vector& _data2) { -> push ebp -> mov ebp,esp ->
我需要在当前表单(代码)的上下文中运行文本文件中的代码。其中一项要求是让代码创建新控件并将其添加到当前窗体。 例如,在Form1.cs中: using System.Windows.Forms; ..
我有此 C++ 代码并将其转换为 C# (.net Framework 4) 代码。有没有人给我一些关于 malloc、free 和 sprintf 方法的提示? int monate = ee; d
我的网络服务器代码有问题 #include #include #include #include #include #include #include int
给定以下 html 代码,将列表中的第三个元素(即“美丽”一词)以斜体显示的 CSS 代码是什么?当然,我可以给这个元素一个 id 或一个 class,但 html 代码必须保持不变。谢谢
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
我试图制作一个宏来避免重复代码和注释。 我试过这个: #define GrowOnPage(any Page, any Component) Component.Width := Page.Surfa
我正在尝试将我的旧 C++ 代码“翻译”成头条新闻所暗示的 C# 代码。问题是我是 C# 中的新手,并不是所有的东西都像 C++ 中那样。在 C++ 中这些解决方案运行良好,但在 C# 中只是不能。我
在 Windows 10 上工作,R 语言的格式化程序似乎没有在 Visual Studio Code 中完成它的工作。我试过R support for Visual Studio Code和 R-T
我正在处理一些报告(计数),我必须获取不同参数的计数。非常简单但乏味。 一个参数的示例查询: qCountsEmployee = ( "select count(*) from %s wher
最近几天我尝试从 d00m 调试网络错误。我开始用尽想法/线索,我希望其他 SO 用户拥有可能有用的宝贵经验。我希望能够提供所有相关信息,但我个人无法控制服务器环境。 整个事情始于用户注意到我们应用程
我有一个 app.js 文件,其中包含如下 dojo amd 模式代码: require(["dojo/dom", ..], function(dom){ dom.byId('someId').i
我对“-gencode”语句中的“code=sm_X”选项有点困惑。 一个例子:NVCC 编译器选项有什么作用 -gencode arch=compute_13,code=sm_13 嵌入库中? 只有
我为我的表格使用 X-editable 框架。 但是我有一些问题。 $(document).ready(function() { $('.access').editable({
我一直在通过本教程学习 flask/python http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-wo
我想将 Vim 和 EMACS 用于 CNC、G 代码和 M 代码。 Vim 或 EMACS 是否有任何语法或模式来处理这种类型的代码? 最佳答案 一些快速搜索使我找到了 this vim 和 thi
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve this
这个问题在这里已经有了答案: Enabling markdown highlighting in Vim (5 个回答) 6年前关闭。 当我在 Vim 中编辑包含 Markdown 代码的 READM
我正在 Swift3 iOS 中开发视频应用程序。基本上我必须将视频 Assets 和音频与淡入淡出效果合并为一个并将其保存到 iPhone 画廊。为此,我使用以下方法: private func d
pipeline { agent any stages { stage('Build') { steps { e
我是一名优秀的程序员,十分优秀!