Constexpr在运行时的性能更差
constexpr performing worse at runtime
我编写了下面的代码来测试constexpr阶乘与普通方法计算所花费的时间
#include<iostream>
#include<chrono>
constexpr long int factorialC(long int x){ return x*(x <2?1 : factorialC(x-1));}
using ns = std::chrono::nanoseconds;
using get_time = std::chrono::steady_clock;
void factorial(long int x){
long int suma=1;
for(long int i=1; i<=x;i++)
{
suma=suma*i;
}
std::cout<<suma<<std::endl;
}
int main(){
long int x = 13;
std::cout<<"Now calling the constexpr"<<std::endl;
auto start1 = get_time::now();
std::cout<<factorialC(x)<<std::endl;
auto end1 = get_time::now();
std::cout<<"Now calling the normal"<<std::endl;
auto start2 = get_time::now();
factorial(x);
auto end2 = get_time::now();
std::cout<<"Elapsed time for constexpr is "<<std::chrono::duration_cast<ns>(end1-start1).count()
<<" Elapsed time for normal is "<<std::chrono::duration_cast<ns>(end2-start2).count()<<std::endl;
}
当我运行代码时,我得到
Now calling the constexpr
1932053504
Now calling the normal
1932053504
Elapsed time for constexpr is 81812 Elapsed time for normal is 72428
但是constexpr
的时间应该接近于"0",因为它已经在编译时计算过了。
但令人惊讶的是,constexpr
的计算比普通的阶乘要花更多的时间。我试着去理解这个问题,但是我不能在我的上下文中理解答案。
请帮我理解一下。
我编译的代码通过(文件名是constexpr.cpp)
g++ --std=c++11 constexpr.cpp
V2 : -
@rici输入后,我将第18行改为
const long int x =13;
结果现在是
Now calling the constexpr
1932053504
Now calling the normal
1932053504
Elapsed time for constexpr is 114653 Elapsed time for normal is 119052
似乎一旦我提到x是const,编译器就会在编译时计算阶乘c
我在windows上使用MinGW32的4.9.3版本的g++
问题是constexpr
是不保证在编译时进行评估。关键字constexpr
只是说它可以,但是编译器也可以在运行时自由地评估它,因为它认为合适。
在运行时间上的差异可能是因为你1)做得不够(一次迭代没什么)和2)递归没有迭代快(我认为,尽管差异很小)。
为了保证编译时求值,必须在编译器必须在编译时求值的上下文中使用,例如模板:
template<unsigned long long n>
auto evaluate() { return n; }
//...
auto start1 = get_time::now();
std::cout << evaluate<factorialC(x)>() << std::endl; //factorialC is evaluted
//at compile timme
auto end1 = get_time::now();
还有evaluate
, std::integral_constant
的标准库函数。
long int x = 13;
这不是一个常量表达式,所以编译器不能在编译时计算factorial(x);
。
尝试向它发送常量值,比如constexpr
值,这样它就可以进行计算了:
int main(){
long int x = 13;
constexpr long y = 13;
std::cout << "Now calling the constexpr" << std::endl;
auto start1 = get_time::now();
// Notice the use of a constexpr value here!
std::cout << factorialC(y) << std::endl;
auto end1 = get_time::now();
std::cout << "Now calling the normal" << std::endl;
auto start2 = get_time::now();
// Simply call your function witha runtime value.
// Try to ensure that the compiler don't inline the obvious value of x
std::cout << factorialC(x) << std::endl;
auto end2 = get_time::now();
std::cout << "Elapsed time for constexpr is "
<< std::chrono::duration_cast<ns>(end1-start1).count()
<< " Elapsed time for normal is "
<< std::chrono::duration_cast<ns>(end2-start2).count()
<< std::endl;
}
顺便说一下,在谈论性能时,你应该将苹果与苹果进行比较。
注意,它不能在编译时计算,因为编译器不知道这个函数中long int x
的值:
constexpr long int factorialC(long int x)
如果需要编译时间阶乘,可以使用模板代替。比如:
#include <iostream>
template<int N> inline int factorial(){ return N*factorial<N-1>(); }
template<> inline int factorial<1>(){ return 1; }
int main()
{
std::cout << factorial<13>() << std::endl;
return 0;
}
相关文章:
- CMake-按正确顺序将项目与C运行时对象文件链接
- 我在c++代码中生成了一个运行时#3异常
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 删除指向指针的指针是运行时错误吗
- 如何用参数值调用函数(仅在运行时已知)
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- c++中的指针和运行时错误
- 在运行时处理类型擦除的数据-如何不重新发明轮子
- 有没有一种方法可以测量c++程序的运行时内存使用情况
- 建议在运行时将带有类实例的列表从c++导入qml
- 无法理解此 return 语句的功能,没有它就会发生运行时错误
- 如何在GTK程序运行时禁用屏幕保护程序/电源管理/屏幕消隐
- 在同一模拟中使用静脉和静脉_ inet内容时出现运行时错误
- 以这种方式在运行时访问元组的性能成本
- 如何在 c++ 目标上提高 antlr4 运行时性能
- Linux 与 Windows,C++读取 CSV 文件的运行时性能差异
- GSL 的预期 (cond) 对运行时施加的性能影响是什么?
- Constexpr在运行时的性能更差
- 性能问题与c++(使用vc++ 2010):在运行时,我的程序似乎随机等待一段时间