2013-04-29 14 views
2

这是微型优化,还是它是最优化的?C++这是微型优化的一种形式

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和作为第二个问题,它看起来像是一个编译器可以优化,但我只是不知道这一点。

回答

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; 

号首先,即使他们是整型,它不会是因为检查而当值很可能大部分时间不为零更多的工作分支优化。

其次,更重要的是,它们是浮动的。这意味着除了you shouldn't directly compare them to 0之外,它们基本上几乎不会完全等于0.因此,if的值为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为真(它不会计算其余部分),那么它将被短路,但是|不会发生。

+0

如果这些值大部分时间都是“int”并且为零,它会不会反效果呢?我的意思是,检查和分支似乎并不比加入零更快。 – zakinster 2013-04-29 17:03:59

+0

@zakinster,如果他们大部分时间都是int并且为零,那真的取决于架构。我和你一起认为最可能的是继续前进并添加它,但你永远不知道所有(奇怪)的体系结构。 – Shahbaz 2013-04-29 17:06:01

+1

即使在大多数情况下它是'int'并且为零,如果'camX'上的缓存读取错误接近100%,它只会更快。 @zakinster – dialer 2013-04-29 17:08:46

2

我怀疑在许多体系结构中,前三行是反优化,因为它们可能会引入浮点比较,然后分支,这比只是总是添加(即使是浮点)要慢。

另一方面,确保在进行转换之前,至少有一个组件是非零的。

对于你的第二种情况,size必须是恒定的时间,几乎肯定会被内联到直接访问vector的大小。这很可能是完全优化的。也就是说,有时它可以通过保存大小来让代码/循环变得更容易阅读,因为它清楚地表明你断言在循环过程中大小不会改变。

2

首先,关于vector.size(),参见 this SO question。在旁注中,我没有看到std::vector::size()不是O(1)的实现。

if (x != 0) camX += x;这个cmp和因此jne然而,要比简单地添加变量x无论如何都要慢。 编辑:除非您预计超过50%的高速缓存未命中的camX

1

第一种可能是pessimisation,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); 
    } 
} 

如果所有的xyz是零,没有什么需要做否则,尽一切努力。

对于第二,编译器可以吊起vector.size()循环外,如果它能够确定的尺寸不同时循环运行而改变。如果编译器无法确定,则不得在循环外部提起计算size()

当你知道尺寸没有改变时自己这样做是一种很好的做法。

+0

我真的很喜欢你的答案。 Pessimization是我不得不添加到字典中的一个新词。 :) 我很喜欢。 – 2013-04-29 17:12:25