threading question 
Author Message
 threading question

Hello,

I have written a multithreaded version of a sequential bioinformatics
application. During testing I noticed that a certain float number was
produced that was off by .00001. For example, instead of 0.11954 being
produced, I would get 0.11955 for a result.

Below is a snippet of code from the thread (they are pooled and generally
there is one thread more than there are CPUs on the system):

void thread_func(some parameters) {
        float mm_score;
        int len1, len2;

        <some code>
        mm_score = some_function();
        <marker 1>
        if <some condition>
                mm_score = 0;
        else {
                mm_score /= (float)<some int>;
                <marker 2>
        }
        <marker 3>
        <use mm_score to do something else>

Quote:
}

At <marker 1> the values of mm_score in both the sequential version of
the tool and in the parallel one are the same. So is the case at <marker
2>. However, as soon the code goes through <marker 2> (which could be
just printf() call to show its value, or anything really), at <marker 3>
it gets "trashed" -> its value changes from, say, 0.11954 (the correct
one) to 0.11955 (the incorrect one).

Now, mm_score and <some int> are both declared within the function that
implements a thread so there are no race conditions. Furthermore, the
application was tested on Compaq Alpha hardware running Linux, OSF/1 and
Tru64, also on sparc running SunOS, SGI running IRIX, ia64 running Linux
and Alpha and x86 running Linux. The incorrect behavior only manifested
itself on the Linux/x86 combo. The same code ran just fine everywhere
else, on machines from 2 to 108 CPUs. The solution I came up with was to
change

float mm_score;

to:

volatile float mm_score;

This solution now works on all platforms, including Linux/x86. My question is: why? :)
 Is it the compiler? I used various compilers on various platforms,
usually gcc but also the native compilers found on all platforms above.
The threading library is pthreads.

Thank you for the time. I wasnt sure if this was the right group(s) the
ask the question but I had no idea where to ask it.

Ognen



Wed, 05 May 2004 03:54:12 GMT  
 threading question


Quote:

> Hello,

> I have written a multithreaded version of a sequential bioinformatics

We won't discuss the multithreading aspects here, because the C language
doesn't define it at all.

Quote:
> application. During testing I noticed that a certain float number was
> produced that was off by .00001. For example, instead of 0.11954 being
> produced, I would get 0.11955 for a result.

Sure. Floating points are not as accurate you imagine.

Quote:
> Below is a snippet of code from the thread (they are pooled and
> generally there is one thread more than there are CPUs on the system):

> void thread_func(some parameters) {
>      float mm_score;

For better results, use double.

--
-ed- emdel at noos.fr
c.l.c.-FAQ http://www.eskimo.com/~scs/C-faq/top.html
C-library: http://www.dinkumware.com/htm_cl/index.html
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/



Wed, 05 May 2004 05:10:23 GMT  
 threading question

Quote:



> > I have written a multithreaded version of a sequential bioinformatics

> We won't discuss the multithreading aspects here, because the C language
> doesn't define it at all.

> > application. During testing I noticed that a certain float number was
> > produced that was off by .00001. For example, instead of 0.11954 being
> > produced, I would get 0.11955 for a result.

His question doesn't seem to have anything to do with threading.
It seems as if his system does something to the data, for unknown
reasons.  His code looks perfectly valid, and should be working as
he expects.

--

   Available for consulting/temporary embedded and systems.
   (Remove "XXXX" from reply address. yahoo works unmodified)



Wed, 05 May 2004 09:26:07 GMT  
 threading question

Quote:

> We won't discuss the multithreading aspects here, because the C language
> doesn't define it at all.

Sorry about the title, it was misleading.If you really bothered to read my posting you would have seen a question still in there.

Quote:
>> application. During testing I noticed that a certain float number was
>> produced that was off by .00001. For example, instead of 0.11954 being
>> produced, I would get 0.11955 for a result.
> Sure. Floating points are not as accurate you imagine.

I know about how accurate floats are, however, that was not the question.

Quote:
>> Below is a snippet of code from the thread (they are pooled and
>> generally there is one thread more than there are CPUs on the system):

>> void thread_func(some parameters) {
>>      float mm_score;
> For better results, use double.

It is not about using the double or float, it is about why declaring a local variable volatile in a threaded function "fixed" the floating point accuracy (or at least made it equal to what the sequential version was producing). A local variable is a local variable, it cannot be affected by another thread, yet it was getting trashed.

Instead of being patronizing, please read the postings before you write a reply.

Ognen



Wed, 05 May 2004 15:01:20 GMT  
 threading question

Quote:


>> > I have written a multithreaded version of a sequential bioinformatics

>> We won't discuss the multithreading aspects here, because the C language
>> doesn't define it at all.

>> > application. During testing I noticed that a certain float number was
>> > produced that was off by .00001. For example, instead of 0.11954 being
>> > produced, I would get 0.11955 for a result.
> His question doesn't seem to have anything to do with threading.
> It seems as if his system does something to the data, for unknown
> reasons.  His code looks perfectly valid, and should be working as
> he expects.

Someone suggested that -ffloat-store switch to gcc might be the solution to this problem. If anyone is interested please email me for the results of the tests.

Thank you,
Ognen



Wed, 05 May 2004 15:05:12 GMT  
 threading question

Quote:

>> We won't discuss the multithreading aspects here, because the C language
>> doesn't define it at all.

>Sorry about the title, it was misleading.If you really bothered to read
>my posting you would have seen a question still in there.

You're being unnecessarily insulting. I'm sure emmanuel did read it,
and gave what he thought were relevant answers.

Quote:
>> For better results, use double.

>It is not about using the double or float,

Are you sure ? The error looks about the right size for that. Still,
you seem insistent so fair enough.

Quote:
>it is about why declaring a local variable volatile in a threaded function
> "fixed" the floating point accuracy (or at least made it equal to what the

if it "fixed" it then its a compiler bug or its a problem caused by
threading. The code ought to have worked.

Quote:
>sequential version was producing). A local variable is a local variable, it
>cannot be affected by another thread, yet it was getting trashed.
>Instead of being patronizing, please read the postings before you write a reply.

Hmm.
--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>


Wed, 05 May 2004 22:16:34 GMT  
 threading question


Quote:
" writes:

...

Quote:
>void thread_func(some parameters) {
>        float mm_score;
>        int len1, len2;

>        <some code>
>        mm_score = some_function();
>        <marker 1>
>        if <some condition>
>                mm_score = 0;
>        else {
>                mm_score /= (float)<some int>;
>                <marker 2>
>        }
>        <marker 3>
>        <use mm_score to do something else>
>}

>At <marker 1> the values of mm_score in both the sequential version of
>the tool and in the parallel one are the same. So is the case at <marker
>2>. However, as soon the code goes through <marker 2> (which could be
>just printf() call to show its value, or anything really), at <marker 3>
>it gets "trashed" -> its value changes from, say, 0.11954 (the correct
>one) to 0.11955 (the incorrect one).

That iasn't exactly "Trashed." :-)

It is common for compilers, particularly x86 ones, to hold values at higher
precision than indicated by the underlying type. On x86 system this allows
values to be held in registers which can greatly speed up code. However
if at some point the compiler has to write the value out to memory
it will have to convert it to a true float format which truncates the
precision it is stored at and therefore can change the value.

Strictly speaking this behaviour is not allowed by the standard however
in most cases the benefits outweigh the problems. A good compiler
should provide an option to enforce the correct standard behaviour but
not all do this perfectly.

Quote:
>Now, mm_score and <some int> are both declared within the function that
>implements a thread so there are no race conditions. Furthermore, the
>application was tested on Compaq Alpha hardware running Linux, OSF/1 and
>Tru64, also on sparc running SunOS, SGI running IRIX, ia64 running Linux
>and Alpha and x86 running Linux. The incorrect behavior only manifested
>itself on the Linux/x86 combo. The same code ran just fine everywhere
>else, on machines from 2 to 108 CPUs. The solution I came up with was to
>change

>float mm_score;

>to:

>volatile float mm_score;

This would effectively force all reads and writes to occur to memory which
ensures a float precision.

Quote:
>This solution now works on all platforms, including Linux/x86. My question is:
> why? :)
> Is it the compiler? I used various compilers on various platforms,
>usually gcc but also the native compilers found on all platforms above.
>The threading library is pthreads.

The x86 FPU architecture holds values at high precision, 80 bits under Linux
and conversions to and from float format occur as part of the memory
store and load operations. Other architectures can load and process
float format directly in registers so there's no format conversion.

Whichever way the implementation works the results are still within the
same error limits. The x86 approach can be more accurate overall, the
only problem is that the results aren't exactly repeatable. The question
is does that matter? Sometimes it does, sometimes it doesn't. If it does
in your case perhaps you could explain why.

--
-----------------------------------------


-----------------------------------------



Wed, 05 May 2004 21:34:26 GMT  
 threading question

Quote:

>>2>. However, as soon the code goes through <marker 2> (which could be
>>just printf() call to show its value, or anything really), at <marker 3>
>>it gets "trashed" -> its value changes from, say, 0.11954 (the correct
>>one) to 0.11955 (the incorrect one).
> That iasn't exactly "Trashed." :-)

Understood. It is only "trashed" as far as my purpose goes :)

Quote:
> Strictly speaking this behaviour is not allowed by the standard however
> in most cases the benefits outweigh the problems. A good compiler
> should provide an option to enforce the correct standard behaviour but
> not all do this perfectly.

gcc (in my case) actually does. It is -ffloat-store as suggested by
another person on comp.unix.programmer. I guess I should have gone through
info gcc before whining on usenet ;). However, my question now is whether
declaring the variable volatile would ensure a portable solution as
opposed to relying on the -ffloat-store or similar switches to different
compilers?

Quote:
> Whichever way the implementation works the results are still within the
> same error limits. The x86 approach can be more accurate overall, the
> only problem is that the results aren't exactly repeatable. The question
> is does that matter? Sometimes it does, sometimes it doesn't. If it does
> in your case perhaps you could explain why.

Well, my program is a threaded implementation of a widely used
bioinformatics tool (not written by me). Even if the x86 solution is "more
accurate" I doubt I would ever convince any of the people using the new
tool that the difference between the "original" and the 'threaded" is due
to the threaded behaving more accurately, if indeed this is the case in
the first place :)

Thank you very much, your responce was educational.

Ognen



Thu, 06 May 2004 00:48:27 GMT  
 threading question

<snip>

Quote:
> float mm_score;

> to:

> volatile float mm_score;

> This solution now works on all platforms, including Linux/x86. My question
> is: why? :)
>  Is it the compiler? I used various compilers on various platforms,
> usually gcc but also the native compilers found on all platforms above.

The x87 FPU has different precision modes, as specified in IEEE 754. The C
compiler might by default set the FPU in higher precision mode than what you
expect, e.g. use extended precision mode (64-bit precision) internally.
Using volatile, you defeat the the internal usage of FPU registers, and the
result gets converted back to the precision you expect.

Some C compilers have a function, which let the programmer set the precision
mode explicit. Check your compiler documentation if such an extension is
available
for you.

--
Tor <torust AT online DOT no>



Thu, 06 May 2004 06:35:52 GMT  
 threading question

<snip>

Quote:
> The x86 FPU architecture holds values at high precision, 80 bits under
Linux
> and conversions to and from float format occur as part of the memory
> store and load operations.

The x87 can operate in different precision modes, AFAIK, single, double and
extended are supported. I expect it's the compiler (not the OS),  which is
responsible for choosing the (default)  precision mode.

Quote:
> Other architectures can load and process
> float format directly in registers so there's no format conversion.

Hmm...so can x87 I guess, what do you imply here is different with x87?
(The Intel double extended format conforms to IEEE.)

--
Tor <torust AT online DOT no>



Thu, 06 May 2004 07:00:54 GMT  
 threading question

Quote:


> >Sorry about the title, it was misleading.If you really bothered to read
> >my posting you would have seen a question still in there.

> You're being unnecessarily insulting. I'm sure emmanuel did read it,
> and gave what he thought were relevant answers.

-hs- comments wasn't (this time) very relevant, they usually are however.

Quote:
> >It is not about using the double or float,

> Are you sure ? The error looks about the right size for that. Still,
> you seem insistent so fair enough.

Typically float maps to IEEE single precision, double to IEEE double
precision and long double to IEEE extended precision. So I guess the usage
of float or double wasn't relevant here, since it's likely that the x87
operated in extended precision internally.

Quote:
> >it is about why declaring a local variable volatile in a threaded
> >function "fixed"
> >the floating point accuracy (or at least made it equal to what the

> if it "fixed" it then its a compiler bug or its a problem caused by
> threading. The code ought to have worked.

Wrong. The compiler is perfectly right to use higher precision
internally. The threading part is totally irrelevant to the discussion at
hand, and BTW the code worked.

--
Tor <torust AT online DOT no>



Thu, 06 May 2004 08:03:42 GMT  
 threading question
On Sun, 18 Nov 2001 01:03:42 +0100, "Tor Rustad"

Quote:



>> >It is not about using the double or float,

>> Are you sure ? The error looks about the right size for that. Still,
>> you seem insistent so fair enough.

>Typically float maps to IEEE single precision, double to IEEE double
>precision and long double to IEEE extended precision. So I guess the usage
>of float or double wasn't relevant here, since it's likely that the x87
>operated in extended precision internally.

The point is, the error looks consistent with the behaviour of a
float. I also read the question originally as "why do i get this
error, and why does it sometimes go away".

Quote:
>> >it is about why declaring a local variable volatile in a threaded
>> >function "fixed" the floating point accuracy (or at least made it equal to what the

>> if it "fixed" it then its a compiler bug or its a problem caused by
>> threading. The code ought to have worked.

>Wrong.

AFAIK there is absolutely no C requirement for the use of volatile to
work. If it does it, then its entirely platform specific and could as
easily be due the interaction between volatile and the threading as to
the internal use of higher-precision representations for floats.

Quote:
>The compiler is perfectly right to use higher precision
>internally.

From an ISO C perspective I think you mean "permitted" rather than
right but I don't disagree in practice.

Quote:
>The threading part is totally irrelevant to the discussion at
>hand,  

You're probably 100% correct. However there's no platform-independent
C way to determine that.

Quote:
>and BTW the code worked.

I said that didn't I ?

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>



Thu, 06 May 2004 16:45:51 GMT  
 threading question


Quote:
>> You're being unnecessarily insulting. I'm sure emmanuel did read it,
>> and gave what he thought were relevant answers.

> -hs- comments wasn't (this time) very relevant <...>

That's true enough, I'm afraid!

--
-ed- emdel at noos.fr
c.l.c.-FAQ http://www.eskimo.com/~scs/C-faq/top.html
C-library: http://www.dinkumware.com/htm_cl/index.html
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/



Thu, 06 May 2004 18:57:07 GMT  
 threading question

Quote:

> On Sun, 18 Nov 2001 01:03:42 +0100, "Tor Rustad"

> The point is, the error looks consistent with the behaviour of a
> float. I also read the question originally as "why do i get this
> error, and why does it sometimes go away".

Your mistake, and please stop calling it an error!

Suggesting a "compiler error", because of some platform dependent floating
point results, isn't something experienced scientific programmers would
dream of without proper analysis. ;-)

Quote:
> >> if it "fixed" it then its a compiler bug or its a problem caused by
> >> threading. The code ought to have worked.

> >Wrong.

> AFAIK there is absolutely no C requirement for the use of volatile to
> work. If it does it, then its entirely platform specific and could as

So what? C floating-point results don't have to be platform independent, C
don't even mandate IEEE 754 conformance, and even among IEEE 754
implementations there are multiple issues which can lead to platform
dependent results.

Quote:
> easily be due the interaction between volatile and the threading as to
> the internal use of higher-precision representations for floats.

Nope, read other posts in this thread for a proper explanation.

--
Tor <torust AT online DOT no>



Thu, 06 May 2004 19:55:43 GMT  
 threading question

Quote:

>>Typically float maps to IEEE single precision, double to IEEE double
>>precision and long double to IEEE extended precision. So I guess the usage
>>of float or double wasn't relevant here, since it's likely that the x87
>>operated in extended precision internally.
> The point is, the error looks consistent with the behaviour of a
> float. I also read the question originally as "why do i get this
> error, and why does it sometimes go away".

Perhaps my English is not good enough to explain myself properly ;). However, I believe I never said something along the
lines of "it sometimes goes away". I think I outlined specifically that it only doesnt work on Linux/x86 platform with
gcc and works everywhere else I tested (sgi irix, sparc/solaris, linux/alpha, linux/ia64, tru64/alpha). I also said that
making a certain local function variable volatile makes things go away, period. Later on in the thread I said that also
using -ffloat-store fixes things without making that variable volatile. So obviously it is not a precision issue, at
least not in the way you are banging at it :). What I need really is the rounding behavior that probably happens when
the float variable is commited from a register to memory. I need this to keep compatible with the same behavior in the
original sequential application I converted to a threaded one. Note that in the sequential application this behavior is
not enforced, it is the same code in the threaded and sequential one, however, when I execute the threaded one even with
one thread in the pool (effectively making it sequential), the problem still occurs. So, the sequential app does not
need the volatile or -ffloat-store switch but the same code in the threaded app does. Does this make things clearer? :)

Ognen



Fri, 07 May 2004 00:18:57 GMT  
 
 [ 25 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Threaded -vs- Multi-threaded Question

2. Exe server threading model - events from worker thread question

3. threading question

4. Complex(?) Threading Question

5. Threading question about PostThreadMessage replacement

6. Forms in Threads Question

7. One more threading question

8. Threading Question

9. Remoting and Multi-thread question

10. Threading question

11. Win32 Thread Question

12. Threads Question

 

 
Powered by phpBB® Forum Software