在释放模式下运行程序
running the program in the Release mode
我想测试大循环中某些代码的执行速度,例如1000000000次。当我在调试模式下运行程序时,我看到超过3.192秒的持续时间,但在发布模式下,持续时间是0.000。我用biger计数器测试了一下,但它是0.000秒。对于我在发布模式中用于计数器(如10000000000)的每一个较大的数字,这个过程和结果都是相等的
问题出在哪里?
我的代码是:
#include<time.h>
#include<iostream>
int main() {
clock_t t1, t2;
double d1 = 97.9834;
double d2 = 897.9134;
double d3 = 0.0;
t1 = clock();
for (size_t i = 0; i < 1000000000; i++)
{
d3 = d1 + d2;
}
t2 = clock();
char msg[100];
sprintf_s(msg, 100, "time is :%.3fn", double(t2 - t1) / 1000.0);
cout << msg << endl;
return 0;
}
编译器需要生成优化的代码,它的行为"就像"它没有做任何优化(除了一些例外,如快速数学浮点优化),除了执行时间。您可以关闭优化,但这样就不会测量优化的代码。
问题的根源是,你无法测量你试图测量的东西,或者你已经得到了正确的结果(循环被优化了,这是应该的)。然而,如果您想强制编译器生成代码,则有一个关键字:volatile
volatile double d1 = 97.9834;
volatile double d2 = 897.9134;
volatile double d3 = 0.0;
现在,编译器需要将变量放入内存,真正读取d1和d2的值,并将结果写入d3,当循环中的加法语句执行此操作时,次数与循环迭代次数一样多。您只能使其中的一个或两个易失性,所以编译器可以跳过一些代码或将非易失性变量保留在寄存器中,这样循环会更快。
在使其中一些变量不稳定后,你是否会测量一些有用的东西,这取决于你实际想要测量的。。。
更多信息:C和C++中volatile的目的是告诉编译器,这个变量有点像内存映射的硬件寄存器,读取或写入它有一些外部影响,所以它永远不能被优化掉。它在PC程序中很少有用,尽管常见的误解与多线程编程无关(不像Java)。
我相信这个for
循环在生产代码中被优化了,因为它没有做任何有用的事情:你从来没有使用过d3
的值,为什么还要计算它呢?
如果希望执行此循环,请关闭优化(将-O0
传递给编译器)。
除了for循环被完全优化之外,clock()
函数并不是世界上最好的测量时间的工具。对于初学者来说,您肯定想做的是开始对clock()
刻度变化进行测量(与高精度计数器相比,clock()
刻度粒度相对较低)。参考CLOCKS_PER_SEC
,例如在MSVC中只有1000。当在clock()
周期的中间开始测量时,结果将非常不一致。
常见的模式是这样做以提高结果的一致性:
clock_t start;
const clock_t tmp = clock();
do {
start = clock();
} while (tmp == start);
// execute the code
const clock_t end = clock();
您必须利用性能测试的结果来防止不必要的优化。一种方法是使变量"不稳定":
#include<time.h>
#include<iostream>
volatile double d = 0;
int main() {
clock_t t1 = clock();
for (size_t i = 0; i < 1000000000; i++)
{
d = 0;
}
clock_t t2 = clock();
std::cout << "time is " << t2 - t1 << std::endl;
// Debug: 3474486
// Release: 484208
return 0;
}
您需要以某种方式向优化器隐藏操作的无用性。但是,由于您想测量优化操作所需的时间,因此在说服优化器不要完全删除操作的过程中,您不希望破坏操作本身的优化。
如果您使d3
和d1
或d2
中的一个具有易失性,则无法对d3 = d1 + d2;
执行太多操作,您可以阻止优化器消除您想要测量的任何工作,但代价是添加一些您可能不想要测量的工作。
在其他情况下,有更好的方法可以防止优化器删除您想要测量的内容。在较大的情况下,一种常见的方法是将关键部分放入不同的编译单元,这样优化器就看不到没有做什么。但在这种情况下,这样做的调用开销甚至比volatile的额外成本还要糟糕。
如果问题是一个简化的"为什么测量时间在发布中不起作用",并且你真的想测量比d3 = d1 + d2;
更复杂的东西,那么你可能会得到更好的帮助,询问你真正想测量什么。但如果目标真的是d3 = d1 + d2;
,那就没有答案了。所花费的时间完全是如何使用它的函数,包括当优化器发现它没有用时,它所花的时间为零。
- 运行程序时出现问题
- 分段错误当我试图运行程序时出错
- C++ 每次运行程序时我都会"nan"输出的问题
- 通过 g++ 运行程序时没有这样的文件或目录
- 重新运行程序和字符串流?
- 无法在 VS Code 上使用代码运行程序运行C++文件
- 使用有限的 RAM 运行 c++ 程序
- 继续运行程序而无需任何干预,直到要求退出为止
- 如何在每次运行程序时写入文件的下一行?
- 控制台在运行C ++程序后立即关闭(无需调试)
- 运行程序时找不到共享对象库,但在编译过程中链接了它
- 远程运行程序
- 在 Heroku 上运行 C++ 程序
- 如何在Powershell中运行C++程序,就像CMD一样?
- 为什么与Java和Python相比,使用Cmake运行C++程序每次都需要这么长时间?
- C++随机数生成器通常在 Visual Studio 中运行程序时在 2 次后停止生成数字
- 崇高文本 3 - 在终端中编译并运行 C++ 程序(路径包含空格)
- 我收到阻止我运行程序的警告,但不确定如何解决
- C++ Visual Studio 无法完全运行程序
- 在SIGABRT c ++信号之后继续运行程序