Jump to content
  • Advertisement
Sign in to follow this  
rldivide

atomic float add ?

This topic is 2075 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

I'm desperatly trying for a week to add one float (at some place in memory) onto another float (at some other place), in an atomic way. Meaning, multiple threads should be able to add values to this memory location without interfering.
I don't wanna use mutex this they would slow down the process a lot.
I couldn't find any answer to this ! Any idea ?
(I just need to do an add, nothing else, no need for a full atomic float class if the problem is simplified this way)

Thanks !

Share this post


Link to post
Share on other sites
Advertisement

It depends on what exactly you want. This

 

add one float (at some place in memory) onto another float (at some other place), in an atomic way.

 

and this:

multiple threads should be able to add values to this memory location without interfering.

 

are very different things.

 

The first thing (adding a value from one [volatile] memory location to a given float value) is impossible to do in a threadsafe manner without a mutex. The second thing (adding some not concurrently chaning value to a given float value) is trivially achieved using std::atomic or manually using a compare-exchange function (casting the float bits to an integer of the same size).

 

Generally, it is trivial to do this:

  • read bit pattern from some address atomically
  • perform any kind of complex operation (including casting to float, adding a value, and casting back)
  • atomically write the new bit pattern using compare-exchange

 

It only gets problematic (requiring a mutex) when there is another memory location you read from involved, and that one might be modified concurrently too.

Edited by samoth

Share this post


Link to post
Share on other sites

Maybe I wasn't clear in the second quote, both quotes are supposed to refer to the same operation: add the value of a float to another float. Unfortunately std::atomic doesn't handle float add operations.

Share this post


Link to post
Share on other sites

wow, your 2nd suggestion does answer my problem very well actually !

I'm actually adding float values from 4 threads to a lot of different random locations in memory. So the case where one thread would access to the same location as another thread is almost null, but I cannot act as if it would never happen ever. So atomicCompareAndStore would succeed a lot of time, and would only have to retry in very rare cases.

So that sound like a perfect solution for me :)

Share this post


Link to post
Share on other sites

The fact that you need to do this hints a bad practice pattern. I suspect that even if you had hw atomic float operations, your algorithm wouldn't scale with cores and fail spectacularly.

 

Why do you need to add floats to random locations from multiple threads?

Edited by Matias Goldberg

Share this post


Link to post
Share on other sites

The fact that you need to do this hints a bad practice pattern. I suspect that even if you had hw atomic float operations, your algorithm wouldn't scale with cores and fail spectacularly.

 

Why do you need to add floats to random locations from multiple threads?

 

My threads do a lot of computation using their own memory space before this float add happen. It's actually the last step, where the result of the computation needs to be stored back into a very large array in memory. Each thread is assigned a fragment (4096 continuous floats) of this very large array, and theses fragments are at random locations and can partially overlap (it depends from what the user do). Because they can overlap (it rarely happen though), I need to handle theses cases as well when the results are stored back.

Edited by rldivide

Share this post


Link to post
Share on other sites

Ok, so far I've wrote this (destination and addvalue are float*):

            float oldval, newval;
            do {
                oldval=*destination;
                newval=oldval+*addvalue;
            } while (!std::atomic_compare_exchange_strong(destination,&oldval,newval));

But it doesn't compile (C2665: 'std::atomic_compare_exchange_strong' : none of the 32 overloads could convert all the argument types). Any idea what I should do ?

Edited by rldivide

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!