C++ C++;这是一种微观优化吗
这是微观优化,还是根本就是优化C++ C++;这是一种微观优化吗,c++,micro-optimization,C++,Micro Optimization,这是微观优化,还是根本就是优化 void Renderer::SetCamera(FLOAT x, FLOAT y, FLOAT z) { // Checking for zero before doing addition? if (x != 0) camX += x; if (y != 0) camY += y; if (z != 0) camZ += z; // Checking if any of the three variables are
void Renderer::SetCamera(FLOAT x, FLOAT y, FLOAT z) {
// Checking for zero before doing addition?
if (x != 0) camX += x;
if (y != 0) camY += y;
if (z != 0) camZ += z;
// Checking if any of the three variables are not zero, and performing the code below.
if (x != 0 | y != 0 | z != 0) {
D3DXMatrixTranslation(&w, camX, camY, camZ);
}
}
你会为……而跑吗。。条件为vector.size()的循环强制应用程序在每个循环中重新计算向量中的元素
std::vector<UINT> vect;
INT vectorSize = vect.size();
for (INT Index = 0; Index < vectorSize; Index++) {
// Do vector processing
}
// versus:
std::vector<UINT> vect;
for (INT Index = 0; Index < vect.size(); Index++) {
// Do vector processing
}
std::vector-vect;
INT vectorSize=vect.size();
对于(INT Index=0;Index
我使用的是Visual Studio,至于第二个问题,编译器似乎可以对其进行优化,但是我不确定。我怀疑在许多体系结构上,前三行是反优化的,因为它们可能会引入浮点比较,然后进行分支,这比总是进行加法(即使是浮点)要慢 另一方面,在进行转换之前确保至少一个组件为非零似乎是合理的
对于第二种情况,
size
必须是常数时间,并且几乎肯定会内联到直接访问向量的size。它很可能是完全可优化的。这就是说,有时它可以通过保存大小使代码/循环更容易阅读,因为这清楚地表明您正在断言大小在循环期间不会改变。取决于向量的实现,编译器可能理解大小没有改变,也可能不理解大小没有改变。毕竟,在循环中调用不同的向量函数,其中任何一个都可能改变大小
因为vector是一个模板,所以编译器知道关于它的一切,所以如果它工作非常努力,它可以理解大小不会改变,但这可能是太多的工作了
通常,您会希望这样写:
for (size_t i = 0, size = vect.size(); i < size; ++i)
...
不。首先,即使它们是int,也不会是优化,因为在大多数情况下,当值可能不是零时,检查和分支需要更多的工作
第二,也是更重要的一点,它们是浮动的。这意味着,除了这一事实,它们基本上永远不会完全等于0。因此,if
s的正确率为99.9999%
同样的道理也适用于此:
if (x != 0 | y != 0 | z != 0)
但是,在这种情况下,由于矩阵转换可能会很昂贵,您可以执行以下操作:
#define EPS 1e-6 /* epsilon */
if (x > EPS || x < -EPS || y > EPS || y < -EPS || z > EPS || z < -EPS)
#定义EPS 1e-6/*epsilon*/
如果(x>EPS | | x<-EPS | y>EPS | y<-EPS | z>EPS | z<-EPS)
现在是的,和矩阵乘法相比,这可能是一个优化
还要注意的是,我使用了|
,例如,如果从一开始x>EPS
为真(它不会计算其余的),它就会短路,但是使用|
则不会发生短路。首先,关于vector.size()
,请参阅
. 另一方面,我还没有看到std::vector::size()
不是O(1)的实现
如果(x!=0)camX+=x
这个cmp
和随后的jne
无论如何都要比简单地添加变量x
慢。编辑:除非您预期在camX上的缓存未命中率远远超过50%
第一个可能是悲观的,否则检查0可能比添加慢。最重要的是,在调用d3dxmatrixtransation
之前的检查中,使用
而不是短路逻辑或|
。由于函数调用之前的检查可能会节省时间(甚至在语义上是必要的),因此将整个代码包装在该检查中
void Renderer::SetCamera(FLOAT x, FLOAT y, FLOAT z) {
if (x != 0 || y != 0 || z != 0) {
camX += x;
camY += y;
camZ += z;
D3DXMatrixTranslation(&w, camX, camY, camZ);
}
}
如果x
、y
和z
全部为零,则无需执行任何操作,否则,全部执行
对于第二种情况,如果编译器能够确定循环运行时大小没有改变,那么它可以将vector.size()
提升到循环外部。如果编译器无法确定这一点,则不能将size()
计算提升到循环之外
当您知道大小没有变化时,您自己这样做是一种良好的做法。如果值在大多数情况下为int
且为零,是否仍会适得其反?我的意思是,检查和分支似乎并不比只加零快。@zakinster,如果它们在大多数时候都是int
和零,那就取决于架构了。我同意你的想法,很可能只是继续添加它会更快,但你永远不知道所有(奇怪的)架构。即使它是int
并且大部分时间为零,只有当camX
上有接近100%的缓存读取未命中时,它才会更快@zakinster@zakinster:一般来说,这会适得其反,或者至少没有什么帮助。如果编译器足够聪明,它将把代码翻译成camX+=x代码>@zakinster:我很确定比较和分支通常比较慢,至少在x86-{32,64}上是这样(假设它没有以某种方式优化)。分支预测没有机会发挥作用,因此阅读cam?
必须花费相当大的成本才能使分支有价值。我非常喜欢你的答案。悲观是我不得不在字典里加上的一个新词我真的很喜欢。
#define EPS 1e-6 /* epsilon */
if (x > EPS || x < -EPS || y > EPS || y < -EPS || z > EPS || z < -EPS)
void Renderer::SetCamera(FLOAT x, FLOAT y, FLOAT z) {
if (x != 0 || y != 0 || z != 0) {
camX += x;
camY += y;
camZ += z;
D3DXMatrixTranslation(&w, camX, camY, camZ);
}
}