Pau*_*zak 69 c++ optimization clock
C++编程语言第4版,第225页读取:只要结果与简单执行顺序的结果相同,编译器就可以重新排序代码以提高性能.一些编译器,例如发布模式下的Visual C++,将重新排序此代码:
#include <time.h>
...
auto t0 = clock();
auto r = veryLongComputation();
auto t1 = clock();
std::cout << r << " time: " << t1-t0 << endl;
Run Code Online (Sandbox Code Playgroud)
进入这种形式:
auto t0 = clock();
auto t1 = clock();
auto r = veryLongComputation();
std::cout << r << " time: " << t1-t0 << endl;
Run Code Online (Sandbox Code Playgroud)
这保证了与原始代码不同的结果(零与大于零的时间报告).有关详细示例,请参阅我的其他问题 这种行为是否符合C++标准?
Jen*_*das 18
好吧,有一些叫做Subclause 5.1.2.3 of the C Standard [ISO/IEC 9899:2011]哪些州:
在抽象机器中,所有表达式都按语义指定进行计算.实际实现不需要评估表达式的一部分,如果它可以推断出它的值未被使用并且不产生所需的副作用(包括由调用函数或访问易失性对象引起的任何副作用).
因此,我真的怀疑这种行为 - 你所描述的行为 - 符合标准.
此外 - 重组确实会对计算结果产生影响,但是如果从编译器的角度来看它 - 它存在于int main()世界中并且在进行时间测量时 - 它会窥视,要求内核给它当前时间,然后去回到主要世界,外面世界的实际时间并不重要.clock()本身不会影响程序,变量和程序行为不会影响clock()函数.
时钟值用于计算它们之间的差异 - 这就是您要求的.如果在两次测量之间发生了某些事情,则与编译器的角度无关,因为您要求的是时钟差异,测量之间的代码不会影响测量过程.
然而,这并未改变所描述的行为非常不愉快的事实.
尽管不准确的测量结果令人不愉快,但它可能会变得更糟,甚至更危险.
请考虑以下从此站点获取的代码:
void GetData(char *MFAddr) {
char pwd[64];
if (GetPasswordFromUser(pwd, sizeof(pwd))) {
if (ConnectToMainframe(MFAddr, pwd)) {
// Interaction with mainframe
}
}
memset(pwd, 0, sizeof(pwd));
}
Run Code Online (Sandbox Code Playgroud)
正常编译时,一切正常,但如果应用优化,memset调用将被优化,这可能导致严重的安全漏洞.为什么要优化出来?这很简单; 编译器再次在其main()世界中思考并认为memset是一个死存储,因为pwd之后不使用该变量而不会影响程序本身.
MSa*_*ers 13
编译器无法交换这两个clock调用.t1必须在之后设定t0.两种调用都是可观察到的副作用.只要观察结果与抽象机器的可能观察结果一致,编译器就可以对这些可观察效果之间的任何内容进行重新排序,甚至可以对可观察到的副作用进行重新排序.
由于C++抽象机器并未正式限制为有限速度,因此它可以veryLongComputation()在零时间内执行.执行时间本身未定义为可观察的效果.真实的实现可能与之匹配.
请注意,很多答案取决于C++标准,而不是对编译器施加限制.
是的,这是合法的 - 如果编译器可以看到clock()调用之间发生的全部代码.