我最近看到了这个关于cpp2015的精彩演讲CppCon 2015: Chandler Carruth "Tuning C++: Benchmarks, and CPUs, and Compilers! Oh My!"
其中提到了一些技术来防止编译器优化代码,包括使用以下函数。
static void escape(void *p) {
asm volatile("" : : "g"(p) : "memory");
}
static void clobber() {
asm volatile("" : : : "memory");
}
void benchmark()
{
vector<int> v;
v.reserve(1);
escape(v.data());
v.push_back(10);
clobber()
}
我正在尝试理解这个问题。以下是问题:
1)转义与覆盖的优势是什么?
2)从上面的例子看来,clobber()似乎阻止了之前的语句(push_back)被优化。如果是这样,为什么下面的代码片段不正确?
void benchmark()
{
vector<int> v;
v.reserve(1);
v.push_back(10);
clobber()
}
如果这还不够令人困惑,Folly(FB的线程库)甚至有一个更奇怪的实现方式。
相关片段:
template <class T>
void doNotOptimizeAway(T&& datum) {
asm volatile("" : "+r" (datum));
}
我的理解是,上面的代码片段告诉编译器汇编块将写入数据。但是,如果编译器发现没有任何使用此数据的消费者,它仍然可以优化掉生产数据的实体,对吗?
我认为这不是常识,任何帮助都将不胜感激!