我正在开发一个游戏引擎,该引擎在Windows上比Linux上慢3-4倍。
我尝试对应用程序进行概要分析,除了在Windows上一切似乎都变慢之外,我没有看到任何特殊问题。
我提取了应用程序的一小部分。我用g++ -O3 perf.cpp
编译它,并执行如下:a.exe 500000000
。结果如下:
源代码:
#include <iostream>
#include <cmath>
#include <vector>
#include <chrono>
struct Vector{
float X, Y, Z;
Vector(float X, float Y, float Z) : X(X), Y(Y), Z(Z){}
Vector vector(const Vector &target) const{
return Vector(target.X - X, target.Y - Y, target.Z - Z);
}
float dotProduct(const Vector &v) const{
return (X*v.X + Y*v.Y + Z*v.Z);
}
};
float compute(const std::vector<Vector> &v){
Vector vec1 = v[0].vector(v[2]);
Vector vec2 = v[1].vector(v[0]);
return vec1.dotProduct(vec2);
}
int main(int argc, char *argv[]){
unsigned int loopMax = atoi(argv[1]);
Vector va(1.5f, 3.0f, 8.0f*loopMax);
Vector vb(1.2f, 2.3f, 11.0f*loopMax);
Vector vc(8.2f, 5.0f, 12.0f*loopMax);
auto frameStartTime = std::chrono::high_resolution_clock::now();
float res = 0.0f;
for(unsigned int i=0; i<loopMax; ++i)
{
res += compute({va, vb, vc});
}
auto frameEndTime = std::chrono::high_resolution_clock::now();
auto diffTimeMicroSeconds = std::chrono::duration_cast<std::chrono::microseconds>(frameEndTime - frameStartTime).count();
std::cout<<"Time: "<<diffTimeMicroSeconds / 1000000.0 <<" sec, res: "<<res<<std::endl;
return 0;
}
我知道一次迭代的差异是荒谬的(<1 us),但结果是我的应用程序慢了3-4倍。
什么可以解释这种差异?如何找到问题?
答案 0 :(得分:3)
尝试在循环外构造compute
的参数。如果编译器没有取消std::vector<Vector>
参数的构造,则很可能会导致堆分配:
std::vector<Vector> arg{va, vb, vc};
for(unsigned int i=0; i<loopMax; ++i)
{
res += compute(arg);
}
如果有堆分配,则很可能比循环内容的其余部分花费更多的时间。堆分配需要多长时间,具体取决于系统和实现。在这两种情况下,删除它都可能会显着提高性能。
如果每次都需要在实际代码中构造向量,则应考虑使用固定大小的数组(原始数组或std :: array),该数组不会在堆上分配,而是在堆栈上分配,这快得多。这似乎适用,因为您恰好在compute
实现中使用了三个元素。
如果您不知道编译时向量的长度 ,并且每次都需要在热循环中对其进行重构,那么您也许可以重用堆-分配的空间,如果您可以为最大长度指定一个很好的猜测,则更是如此:
std::vector<Vector> arg;
arg.reserve(1000); // Allocate for up to 1000 element
for(unsigned int i=0; i<loopMax; ++i)
{
arg.clear();
arg.push_back(va);
[...]
arg.push_back(vn);
res += compute(arg);
}