[Solved] Different results in debug and release modes



  • Hi all,
    I have a quite small program that is working well in debug mode. I have though completely different results in the release mode.
    My program:
    I have a very simple class:

    @
    class myclass
    {
    public:
    int Z;
    float conc,min,max,step;
    };
    @

    I make an array of objects:
    @
    myclass *Cons=new myclass[30];
    or myclass Cons[30];
    @

    I initialize only the objects that I need (<30).
    and the problem comes here:
    I evaluate the number of steps required to change the the conc from min to max using the step step. I do this for nbCons objects:

    @
    nbSim=0;
    for (int i=0;i<=nbCons-1;i++)
    for (float c=Cons[i].min;c<=Cons[i].max;c+=Cons[i].step)
    nbSim++;
    @

    and JUST AFTER this I do the same loop but with some codes inside. The codes don't touch the objects' members value anyway:

    @
    n=0;
    for (int i=0;i<=nbCons-1;i++)
    for (float c=Cons[i].min;c<=Cons[i].max;c+=Cons[i].step)
    {
    //some code here

        n++;
        }
    

    @

    What I can't understand is

    • in debug mode, nbSim=n which is normal

    • in release mode, I have a different value of nbSim than the one in debug mode. and it's also different of n

    I tried to put something like qDebug << Cons.min in the second loop and commented all the (//some code here) and then n is also different from n without qDebug in release mode. (I hope you understand what I mean:)
    Some ideas?
    Thanks in advance.



  • Try putting brackets for the first for loop as well.



  • Thank you for the answer. I tried it but no change (as expected).



  • In release:
    @
    int Z;
    float conc,min,max,step;
    @
    those are not initialized with 0, as it is in debugmode. So initialize them with 0 in the constructor of your class.



  • Thank you but before these instructions, I initialized already all these members.
    The problem seems to come from the object but I don't know where (I'm not so experienced).
    I tried to use vector of myclass and resize it when needed but the results are the same.
    @
    vector<myclass> Cons;
    Cons.resize(nbCons);
    @



  • So I just took the first loop to calculate nbSim to see what's wrong. I found out that if I put a qDebug() << c inside the loop, the results are the same in debug and release modes. I think it's related to float precision or what?? I really have no idea. Any help please.


  • Moderators

    Kind of off the subject, but if you have the code:
    @
    for (float c=Cons[i].min;c<=Cons[i].max;c+=Cons[i].step)
    nbSim++;
    @
    whose sole purpose is to calculate the number of steps needed, why not just use
    @
    int nbSim = ((Cons[i].max - Cons[i].min) / Cons[i].step) + 1;
    @

    Furthermore, why not make it a utility method in your class:
    @
    class myclass
    {
    public:
    myclass() {
    Z = 0;
    conc = min = max = step = 0.0f;
    }

    int numSteps() {
    return ((Cons[i].max - Cons[i].min) / Cons[i].step) + 1;
    }

    int Z;
    float conc,min,max,step;
    };
    @

    Also, consider using Qt's containers (QList, QVector, etc.) in place of a stdc++ vector or an array. Then you could use
    @
    QList<myclass> Cons;
    ...

    foreach (myclass item, Cons)
    {
    ... do something with each one ...
    }
    @



  • Thanks for the hints. I began like that to calculate nbSim. Then seeing the difference in the results, I thought doing exactly the same thing may solve it, which was not the case.
    I have tried the following simple example:
    @
    float min=1.8541,max=20.54335,step=0.00014521;

    int i=0;
    for (float f=min;f<=max;f+=step)
    {        
        i++;
    }
    

    @

    and actually the results are DIFFERENT in debug (128814) and release mode (128705).
    So I think my problem comes really from this floating point behavior. Can someone tell me how to deal with this? Is it a bug or is it normal?


  • Moderators

    I don't think it's a bug, per se, as I'm sure that there are different floating-point handling procedures in place when you're in debug mode. In release mode, the compiler may optimize things slightly different.

    Since floating point precision is always an issue, it doesn't seem to me to be out of the realm of normal operations.

    You might try using doubles instead of floats for more precision.


  • Moderators

    Your release mode value is closer to what you would obtain by building the difference and divide by step.

    However, as mlong pointed out, why are you doing this?

    BTW float has typically about 6-7 digits when expressed as 4 byte. So you are right at the limit, if your compiler does not use a double internally.

    The difference might be a result from internal casting from double to float and vis versa. If you really want to do what you do, try to do it at least with double, which shall be 8 byte in most compilers.



  • Thank you all for your reply. Using double did in fact SOLVE the problem. I was though skeptical as in my real work, I don't have so "big" numbers. I have an example below where I have 9 objects Cons. I give here the min, max and step values for all 9 objects

    @MIN:
    3.239
    7.16
    6.855
    0.979
    5.77
    6.37
    6.415
    6.47
    6.74@

    @MAX:
    9.716
    21.48
    20.57
    2.937
    17.31
    19.11
    19.24
    19.41
    20.22@

    @STEP:
    0.3239
    0.716
    0.6855
    0.0979
    0.577
    0.637
    0.6415
    0.647
    0.674@

    Again, thanks a lot for your contributions.


  • Moderators

    Good to see that your issue has been solved.

    The whole issue is completely depending on the HW, OS, compiler and their options. A general answer was not really possible on your initial input.

    Compilations in debug mode and release mode will typically provide different answers for problems similar to yours. Even for double numbers you may see issues when approaching situations where you are getting close to their typically 16(?) significant digits. Some of the numeric processing is optimized by the HW for Intel's math co-processors. They convert 8 byte doubles to 10 bytes doubles for carrying out the math. However, by standard most compilers are handling doubles only with 8 bytes. This requires a couple transformations forth and back again, when numbers are loaded and stored again. In most cases this is of no issue.

    For you it is likely that the 4 byte float is transformed to a 10 byte double for calculations and transformed back to 4 byte. Optimizing is often trying, depending on the actual compile settings, to avoid those translations forth back. You have to dig quite deeply with the details of HW, OS, ... for getting a definite answer. However, the results you have provided do back those assumptions.

    Finally you might want to mark your thread with [Solved] in the title.



  • How do I mark it as solved?


  • Moderators

    Either you found already or a moderator has done for you.

    For next time in case it was a moderator. You should be able to edit any of your entries. Just at the right of your text below your avatar is an edit link. If you do in the opening post, you can edit the title line.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.