这是微观优化,还是优化呢?
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()的条件的for循环会强制应用程序重新计算每个循环中向量中的元素吗?
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
}
我正在使用Visual Studio,而对于第二个问题,它似乎是编译器可以优化的东西,但我只是不确定。
答案 0 :(得分:5)
根据向量的实现,编译器可能会或可能不会理解大小未更改。毕竟,你在循环中调用不同的向量函数,其中任何一个都可能改变大小。
因为vector是一个模板,所以编译器知道它的一切,所以如果它真的很难,它可以理解大小不会改变,但这可能太多了。
通常,你会想这样写:
for (size_t i = 0, size = vect.size(); i < size; ++i)
...
虽然我们正在使用它,但迭代器使用了类似的方法:
for (list<int>::iterator i = lst.begin(), end = lst.end(); i != end; ++i)
...
编辑:我错过了第一部分:
这是优化吗?
if (x != 0) camX += x;
if (y != 0) camY += y;
if (z != 0) camZ += z;
没有。首先,即使它们是int,也不是优化,因为检查和分支时值很可能是大多数时候不是零是更多的工作。
其次,更重要的是,它们是浮动的。这意味着除了you shouldn't directly compare them to 0之外,它们基本上几乎不会完全等于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)
现在是的,与矩阵乘法相比,这可能是一种优化。
另请注意,我使用的||
会被短路,例如从开头x > EPS
开始就是真的(它不会计算其余部分),但|
表示{{1}}不会发生。
答案 1 :(得分:2)
我怀疑在许多架构上前三行都是反优化,因为它们可能引入浮点比较然后分支,这可能比只是总是进行加法更慢(即使它是浮点数)。
另一方面,确保在进行转换之前至少有一个组件非零是正确的。
对于您的第二种情况,size
必须是固定时间,并且几乎可以肯定地直接访问vector
的大小。它很可能完全可以优化。也就是说,有时它可以通过保存大小来更容易地读取代码/循环,因为这清楚地表明你断言大小在循环期间不会改变。
答案 2 :(得分:2)
首先,关于vector.size()
,请参阅
this SO question。另外,我还没有看到std::vector::size()
不是O(1)的实现。
if (x != 0) camX += x;
此cmp
和后续jne
会比简单地添加变量x
更慢,无论如何。 编辑:除非您预计camX
答案 3 :(得分:1)
第一个可能是悲观,0的检查可能比添加慢。最重要的是,在致电D3DXMatrixTranslation
之前的检查中,您使用的是|
,而不是短路逻辑或||
。由于函数调用之前的检查可能节省了时间(甚至在语义上是必需的),因此将整个代码包装在该检查中,
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()
计算。
当你知道尺寸没有改变时,你自己这样做是好的做法。