سؤال

Is this micro-optimization, or is it optimization at all?

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);
    }
}

Would running a for.. loop with the condition having vector.size() force the application to recount the elements in the vector on each loop?

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
}

I'm using Visual Studio and as for the second question, it seems like something a compiler could optimize, but I'm just not sure on that.

هل كانت مفيدة؟

المحلول

Depending on the implementation of vector, the compiler may or may not understand that size is not changed. After all, you call different vector functions inside the loop, any of which might change size.

Since vector is a template, then the compiler knows everything about it, so if it works really hard, it could understand that size doesn't change, but that's probably too much work.

Often, you would want to write like this:

for (size_t i = 0, size = vect.size(); i < size; ++i)
    ...

While we're at it, a similar approach is used with iterators:

for (list<int>::iterator i = lst.begin(), end = lst.end(); i != end; ++i)
    ...

Edit: I missed the first part:

Is this optimization?

if (x != 0) camX += x;
if (y != 0) camY += y;
if (z != 0) camZ += z;

No. First of all, even if they were int, it wouldn't be optimization since checking and branching when the values are probably most of the times not zero is more work.

Second and more importantly, they are float. This means that besides the fact that you shouldn't directly compare them to 0, they are basically almost never exactly equal to 0. So the ifs are 99.9999% true.

Same thing applies to this:

if (x != 0 | y != 0 | z != 0)

In this case however, since matrix translation could be costly, you could do:

#define EPS 1e-6 /* epsilon */
if (x > EPS || x < -EPS || y > EPS || y < -EPS || z > EPS || z < -EPS)

and now yes, comparing to a matrix multiplication, this is probably an optimization.

Note also that I used || which gets short-circuited if for example right from the beginning x > EPS is true (it won't calculate the rest), but with | that won't happen.

نصائح أخرى

I suspect that on many architectures the first three lines are an anti-optimization because they may introduce a floating point compare and then branch which can be slower than just always doing the addition (even if it's floating point).

On the other hand making sure that at least one component is non-zero before doing the transformation seems sound.

For your second case, size has to be constant time and will almost certainly be inlined out to a direct access to the vector's size. It's most likely fully optimizable. That said, sometimes it can make the code/loop easier to read by saving the size off because that clearly shows you are asserting the size won't change during the loop.

Firstly, Regarding the vector.size(), see this SO question. On a side note, I haven't seen an implementation where std::vector::size() isn't O(1).

if (x != 0) camX += x; this cmp and consequent jne however is going to be slower than simply adding the variable x no matter what. Edit: Unless you expect well over 50 % cache misses on camX

The first one is probably a pessimisation, the check for 0 is probably slower than the addition. On top of that, in the check before the call to D3DXMatrixTranslation, you use | instead of the short-circuiting logical or ||. Since the check before the function call is probably a time-saver (or even semantically necessary), wrap the entire code in that check,

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);
    }
}

if all of x, y and z are zero, nothing need be done, otherwise, do all.

For the second, the compiler can hoist the vector.size() outside the loop if it can determine that the size doesn't change while the loop runs. If the compiler cannot determine that, it must not hoist the size() computation outside the loop.

Doing that yourself when you know that the size doesn't change is good practice.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top