如何强制编译器不跳过我的函数调用?
How do I force the compiler not to skip my function calls?
假设我想对某个函数double a(double b, double c)
的两个相互竞争的实现进行基准测试。我已经有一个大的array <double, 1000000> vals
,我可以从中获取输入值,所以我的基准测试看起来大致如下:
//start timer here
double r;
for (int i = 0; i < 1000000; i+=2) {
r = a(vals[i], vals[i+1]);
}
//stop timer here
现在,一个聪明的编译器可以意识到我只能使用最后一次迭代的结果,并简单地杀死其余的,留给我double r = a(vals[999998], vals[999999])
。这当然违背了基准测试的目的。
是否有一个好的方法(如果它在多个编译器上工作则加分)来防止这种优化,同时保持所有其他优化?
(我已经看到关于插入空asm
块的其他线程,但我担心这可能会阻止内联或重新排序。我也不是特别喜欢在每次迭代期间添加结果sum += r;
的想法,因为这是不应该包含在结果计时中的额外工作。为了这个问题的目的,如果我们能专注于其他替代解决方案,那就太好了,尽管对于对此感兴趣的人来说,在评论中有一个热烈的讨论,共识是+=
在许多情况下是最合适的方法。)
将a
放在单独的编译单元中,并且不使用LTO(链接时间优化)。这种方式:
- 循环总是相同的(由于基于
a
的优化而没有差异) - 函数调用的开销总是相同的
- 要测量纯粹的开销并有一个基线来比较实现,只需对
a
的空版本进行基准测试
请注意,编译器不能假设对a
的调用没有副作用,因此它不能优化循环并将其替换为最后一次调用。
一种完全不同的方法可以使用RDTSC,它是CPU核心中的硬件寄存器,用于测量时钟周期。它有时对微基准测试很有用,但正确理解结果并非微不足道。例如,查看这个并搜索/搜索SO以获取有关rdtsc的更多信息。
相关文章:
- 我的函数调用 (C++) 中的未声明标识符
- 钩/绕道 d3d9 (现在/结束场景) - 似乎调用我的函数然后崩溃
- 阻止我的项目调用__CxxFrameHandler3(CRT函数)
- 当我从头文件和实现文件调用我的函数到我的主文件时,我没有得到任何输出
- C ++尝试访问映射中的元素会给我一个不匹配的函数调用错误
- 为什么我不能在插入的函数调用中直接使用返回的指针作为参数
- 我的C++函数似乎没有被调用
- C++模板:无法从 main.cpp 调用我的函数
- 我的函数返回的是打印到控制台,它只会在我调用它时每隔一段时间C++
- 为什么我的函数调用与此泛型函数实现不匹配?
- 如何在运行时链接期间从我的 DLL 调用函数
- P/调用语法 - 我是否在 C# 中正确翻译了我的C++函数
- 当我使用由unsigned int和unsigned long区分的重载函数时,引发了不明确的函数调用错误?这种重载有效
- 为什么我的函数在调用时不起作用?
- 第一次制作了一个跨越几个类的程序,但我在函数调用方面遇到了问题
- 我想用字符串参数调用我的函数
- 似乎无法调用我的函数
- 我的函数调用出错了,有人能解释一下原因吗
- 什么是错误的visual c++我的函数调用
- 如何强制编译器不跳过我的函数调用?