我有这段代码:
#include <iostream>
#include <thread>
long int global_variable;
struct process{
long int loop_times_ = 0;
bool op_;
process(long int loop_times, bool op): loop_times_(loop_times), op_(op){}
void run(){
for(long int i=0; i<loop_times_; i++)
if (op_) global_variable+=1;
else global_variable-=1;
}
};
int main(){
struct process p1(10000000, true);
struct process p2(10000000, false);
std::thread t1(&process::run, p1);
std::thread t2(&process::run, p2);
t1.join();
t2.join();
std::cout <<global_variable<< std::endl;
return 0;
}
Main 函数启动两个线程来递增和递减一个全局变量。 如果我用这个编译:
g++ -std=c++11 -o main main.cpp -lpthread
我在每次执行中得到不同的输出。 但是如果我添加 -O3 并用这个编译:
g++ -O3 -std=c++11 -o main main.cpp -lpthread
每次输出都是零
这里发生了什么样的优化来消除我的关键部分,我怎样才能欺骗编译器不优化它?
编辑:操作系统:Ubuntu 16.04.4,g++:5.4.0
最佳答案
很可能您的 run 方法被优化为等同于:
void run(){
if (op_) global_variable += loop_times_;
else global_variable -= loop_times_;
这是编译器可以利用可用信息轻松完成的事情。
要欺骗编译器,您必须确保循环在每次迭代中添加或减去 1 且没有其他副作用并不明显。
尝试在循环中添加一个函数调用,它只会在名为 totalIterationsDone
的对象上增加一个简单的计数器,或类似的东西。这可能会迫使编译器实际执行循环。将循环变量作为参数传递也可能会强制它跟踪 i
的中间值。
struct process{
long int loop_times_ = 0;
bool op_;
long int _iterationsDone = 0;
process(long int loop_times, bool op): loop_times_(loop_times), op_(op){}
void run(){
for(long int i=0; i<loop_times_; i++){
if (op_) global_variable+=1;
else global_variable-=1;
Trick(i);
}
}
void Trick(int i){
_iterationsDone += 1;
}
};
关于c++ - -O3循环增量优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42789511/