我最近遇到了这个辉煌的cpp2015演讲CppCon 2015:Chandler Carruth"调优C++:基准测试,CPU和编译器!哦,我的!"
提到的阻止编译器优化代码的技术之一是使用以下函数.
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()
}
Run Code Online (Sandbox Code Playgroud)
我试图理解这一点.问题如下.
1)越过clobber逃脱的好处是什么?
2)从上面的例子看起来,clobber()可以防止先前的语句(push_back)被优化.如果是这样的话,为什么下面的代码片段不正确?
void benchmark()
{
vector<int> v;
v.reserve(1);
v.push_back(10);
clobber()
}
Run Code Online (Sandbox Code Playgroud)
如果这不够混乱,那么愚蠢(FB的线程化lib)就会有一个更奇怪的实现
相关片段:
template <class T>
void doNotOptimizeAway(T&& datum) {
asm volatile("" : "+r" (datum));
}
Run Code Online (Sandbox Code Playgroud)
我的理解是上面的片段通知编译器程序集块将写入数据.但是如果编译器发现没有这个数据的消费者,它仍然可以优化生成数据的实体吗?
我认为这不是常识,任何帮助表示赞赏!
我正在阅读预防编译器优化,同时描述Chandler Carruths 如何clobber()和escape()来自 CppCon 2015:Chandler Carruth"调优C++:基准测试,CPU和编译器!哦我的!".影响编译器.
从阅读那里,我假设如果我有一个输入约束,如"g"(val),那么编译器将无法优化val.但是在g()下面,没有生成代码.为什么?
如何doNotOptimize()重写以确保生成代码g()?
template <typename T>
void doNotOptimize(T const& val) {
asm volatile("" : : "g"(val) : "memory");
}
void f() {
char x = 1;
doNotOptimize(&x); // x is NOT optimized away
}
void g() {
char x = 1;
doNotOptimize(x); // x is optimized away
}
Run Code Online (Sandbox Code Playgroud)
c++ assembly inline-assembly performance-testing compiler-optimization
我正在评估我的项目的网络+渲染工作负载。
程序连续运行一个主循环:
while (true) {
doSomething()
drawSomething()
doSomething2()
sendSomething()
}
Run Code Online (Sandbox Code Playgroud)
主循环每秒运行 60 多次。
我想查看性能故障,每个程序需要多少时间。
我担心的是,如果我打印每个程序的每个入口和出口的时间间隔,
这会导致巨大的性能开销。
我很好奇什么是衡量性能的惯用方法。
日志打印是否足够好?