jav*_*ver 1 c++ optimization indirection c++14
我刚发现间接成本大约是浮点乘法的3倍!
这是预期的吗?我的考试错了吗?
在我读了指针间接对效率有多大影响?,我对间接成本感到恐慌.
由于现代CPU的工作原理,通过指针间接可能要慢得多.
在我过早优化我的真实代码之前,我想确保它真的花费很多,因为我担心.
我做了一些技巧来找到粗略数字(3x),如下所示: -
我发现Test2需要更多的时间来测试Test1.
这里没什么好惊讶的.
我尝试将我的代码更改calculate something expensive为更加昂贵,以使两个测试成本接近相同.
最后,我发现使两个测试使用相同的时间(即收支平衡)的可能功能之一是: -
float*float*...3次 float 这是我的测试用例(ideone演示): -
class C{
public: float hello;
public: float hello2s[10];
public: C(){
hello=((double) rand() / (RAND_MAX))*10;
for(int n=0;n<10;n++){
hello2s[n]= ((double) rand() / (RAND_MAX))*10;
}
}
public: float calculateCheap(){
return hello;
}
public: float calculateExpensive(){
float result=1;
result=hello2s[0]*hello2s[1]*hello2s[2]*hello2s[3]*hello2s[4];
return result;
}
};
Run Code Online (Sandbox Code Playgroud)
这是主要的: -
int main(){
const int numTest=10000;
C d[numTest];
C* e[numTest];
for(int n=0;n<numTest;n++){
d[n]=C();
e[n]=new C();
}
float accu=0;
auto t1= std::chrono::system_clock::now();
for(int n=0;n<numTest;n++){
accu+=d[n].calculateExpensive(); //direct call
}
auto t2= std::chrono::system_clock::now();
for(int n=0;n<numTest;n++){
accu+=e[n]->calculateCheap(); //indirect call
}
auto t3= std::chrono::system_clock::now();
std::cout<<"direct call time ="<<(t2-t1).count()<<std::endl;
std::cout<<"indirect call time ="<<(t3-t2).count()<<std::endl;
std::cout<<"print to disable compiler cheat="<<accu<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)
直接呼叫时间和间接呼叫时间被调整为与上面提到的相似(通过编辑calculateExpensive).
间接成本= 3倍浮点乘法.
在我的桌面(带有-O2的Visual Studio 2015)中,它是7倍.
是否可以预期间接成本约为浮动乘法的3倍?
如果不是,我的测试怎么错了?
(感谢enhzflep建议改进,它被编辑.)
简而言之,您的测试非常不具代表性,并且实际上并不能准确地测量您的想法.
请注意,您拨打了new C()100'000次.这将在你的记忆中创造100'000个C散射实例,每一个都非常小.如果您的内存访问是常规的,现代硬件非常擅长预测.由于每次分配,每次调用new都与其他分配无关,因此内存地址不能很好地组合在一起,这使得预测更加困难.这导致所谓的缓存未命中.
分配为数组(new C[numTest])可能会产生完全不同的结果,因为在这种情况下地址是非常可预测的.尽可能地将您的记忆分组并以线性,可预测的方式访问它通常会提供更好的性能.这是因为大多数缓存和地址预取器都期望这种模式恰好出现在常见程序中.
次要添加:像这样初始化C d[numTest] = {};将在每个元素上调用构造函数