Page 3 of 3

Re: Quiz

PostPosted: Thu Dec 10, 2009 5:38 am
by CoMPMStR
Well the only thing I can think of that can be any faster is using a prefix operation.
Code: Select all
for ( int I = iTotal; --I >= 0; ) {
    // Do something.
}


Couldn't this be used as well?
Code: Select all
for ( int I = -1; ++I < iTotal; ) {
    // Do something.
}

Re: Quiz

PostPosted: Thu Dec 10, 2009 6:08 am
by cobr_h
this quiz as it solves out is getting very interesting. in the end someone should make up a compile of the best answers. Thought, for example, that var != var was quite an bitwise operation. Well, I thought the compiler just interpreted that as a bitwise check. Maybe it does if we play hard with compiler flags.

At least I once could make an application run 3 times faster by using aggressive optimization flags on the compiler. Of course I checked the end value and compared different flags to see if a flag was breaking the result.

3 times faster. It sounds like nothing but it was a simulation that used to take over four weeks to run entirely (a month). Another optimization was to use openMP to spread processes between the eight processors on the rig. Resulting then ~6 times over the already three times faster execution. Rounding down I could safely say the simulation ran 5x3=15 times faster. A month worth job ran in 10 hours. Just a matter of optimization.

Well, to attain that I used intel specific compiler on intel specific processor, and a newer xeon (dual quad) which implements new ssse4 or 4.1 instruction sets. On older xeon, which had only sse3, the optimizations were in the end like 5 or 10 (not well measured) times faster. Faster than no optimization but far from the one I could do with newer xeon.

Re: Quiz

PostPosted: Thu Dec 10, 2009 7:20 am
by L. Spiro
CoMPMStR wrote:Well the only thing I can think of that can be any faster is using a prefix operation.
Code: Select all
for ( int I = iTotal; --I >= 0; ) {
    // Do something.
}

Correct.

If we can not assume we are allowed to modify iTotal then we use a standard iterator from iTotal down to 0.
If we can modify iTotal, it would be better to use iTotal directly in place of I as has been suggested earlier.
Either way, the structure of the loop changes slightly to accommodate the new ability we have to check against being below 0.

The basic rule of optimization that all children learn in preschool is that prefix is never slower than and sometimes faster than postfix. We want to use it when possible, but our previous loops were forced into postfix simply because of the unsigned nature of being unable to compare below 0.
Postfix still provides the best performance of any alternative in those cases, but simply by changing the sign we gain access to the best possible case, which generates the smallest and fastest code you can get.

If you are a Java coder, this is going to be by far your loop of choice. Java has no unsigned type, so all of your loops will be signed. This loop is especially fast and small in Java, so it is an absolute must for Java programmers.



Who knew that basic loops could be so challenging/involved? Look under every rock and question everything. Just because it is exceptionally common does not mean it is correct or could not be improved.


CoMPMStR wrote:Couldn't this be used as well?
Code: Select all
for ( int I = -1; ++I < iTotal; ) {
    // Do something.
}

Prefix increment is not the only optimization making the loop into its 100% form. Checking against 0 helps greatly, as there are a million ways for the compiler to do it and all are faster and smaller than loading a variable into memory and checking against it.
If you have to go from 0 to iTotal (because the loop internals require it etc.) then the most common form is better than this. This loop adds an additional increment operation over the traditional loop, and the traditional loop can still use ++I. It is also difficult to understand when people have to go over your code in the future, but then again many of these optimizations result in less-common code. Just not as uncommon as this.


L. Spiro


P. S.: For some reason the 100% form of the unsigned loop does not work in L. Spiro Script. It skips index 0.
I will investigate and fix later but be warned that you can not use the unsigned form yet.
You can, however, use the signed form.

Re: Quiz

PostPosted: Thu Dec 10, 2009 10:40 am
by CoMPMStR
L. Spiro wrote:P. S.: For some reason the 100% form of the unsigned loop does not work in L. Spiro Script. It skips index 0.
I will investigate and fix later but be warned that you can not use the unsigned form yet.
You can, however, use the signed form.


The same thing happens when using int as well. Here's an example, in LSS I put this and it counts from 9 to 1:
Code: Select all
int iTotal = 10;
for(int I = iTotal; I--;) {
    PrintF("%d", I);
}

Buf if I try it with VS, it counts from 9 to 0. Using the postfix decrement works as the prefix should, so it appears, but the increment works fine. For example, if you try for(int I = -iTotal; I++;) it will count from -9 to 0 whereas for(int I = -iTotal; ++I;) counts from -9 to -1. :?

Re: Quiz

PostPosted: Wed Apr 28, 2010 12:20 am
by troublesh00ter
Is there any way we could continue this? I have very much enjoyed it before ;)

Re: Quiz

PostPosted: Fri Apr 30, 2010 10:18 am
by L. Spiro
I may think of some more questions in the future.


L. Spiro