Ste*_*sop 9 c++ optimization gcc
这是一些代码(完整程序后面的问题):
template <typename T>
T fizzbuzz(T n) {
T count(0);
#if CONST
const T div(3);
#else
T div(3);
#endif
for (T i(0); i <= n; ++i) {
if (i % div == T(0)) count += i;
}
return count;
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我用这个模板函数调用int,那么根据我是否定义CONST,我得到6个性能差异:
$ gcc --version
gcc (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
$ make -B wrappedint CPPFLAGS="-O3 -Wall -Werror -DWRAP=0 -DCONST=0" &&
time ./wrappedint
g++ -O3 -Wall -Werror -DWRAP=0 -DCONST=0 wrappedint.cpp -o wrappedi
nt
484573652
real 0m2.543s
user 0m2.059s
sys 0m0.046s
$ make -B wrappedint CPPFLAGS="-O3 -Wall -Werror -DWRAP=0 -DCONST=1" &&
time ./wrappedint
g++ -O3 -Wall -Werror -DWRAP=0 -DCONST=1 wrappedint.cpp -o wrappedi
nt
484573652
real 0m0.655s
user 0m0.327s
sys 0m0.046s
Run Code Online (Sandbox Code Playgroud)
检查反汇编表明,在快速(常量)情况下,模数已经变成了乘法和移位类型的东西,而在慢速(非常量)情况下,它正在使用idivl.
更糟糕的是,如果我尝试将我的整数包装在一个类中,那么无论我是否使用const,都不会发生优化.代码总是使用idivl和运行缓慢:
#include <iostream>
struct WrappedInt {
int v;
explicit WrappedInt(const int &val) : v(val) {}
bool operator<=(const WrappedInt &rhs) const { return v <= rhs.v; }
bool operator==(const WrappedInt &rhs) const { return v == rhs.v; }
WrappedInt &operator++() { ++v; return *this; }
WrappedInt &operator+=(const WrappedInt &rhs) { v += rhs.v; return *this; }
WrappedInt operator%(const WrappedInt &rhs) const
{ return WrappedInt(v%rhs.v); }
};
std::ostream &operator<<(std::ostream &s, WrappedInt w) {
return s << w.v;
}
template <typename T>
T fizzbuzz(T n) {
T count(0);
#if CONST
const T div(3);
#else
T div(3);
#endif
for (T i(0); i <= n; ++i) {
if (i % div == T(0)) count += i;
}
return count;
}
int main() {
#if WRAP
WrappedInt w(123456789);
std::cout << fizzbuzz(w) << "\n";
#else
std::cout << fizzbuzz<int>(123456789) << "\n";
#endif
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:
1)C++本身有一个简单的原理,或gcc的优化,它解释了为什么会发生这种情况,或者只是"各种启发式运行,这是你得到的代码"的情况?
2)有没有办法让编译器意识到我的本地声明和从未引用的const WrappedInt可以被视为编译时const值?我希望这个东西能够直接替代模板中的int.
3)是否有一种已知的包装int的方法,以便编译器在优化时可以丢弃包装?目标是WrappedInt将是一个基于策略的模板.但是,如果"无所事事"政策导致基本上任意的6倍速度惩罚超过int,我最好特殊情况下直接使用int.