June 9, 2010

SABROG SABROG
Lab Rat
82 posts

QAtomicInt

 

Why QAtomicInt doesn’t have atomic operations like in std::atomic<int>::load/store? How i can assign and get int atomically if this operations not atomic?:

  1.     inline QAtomicInt(int value = 0)
  2.     {
  3.         _q_value = value;
  4.     }
  5.  
  6. inline QAtomicInt(int value = 0)
  7.     {
  8. #ifdef QT_ARCH_PARISC
  9.         this->_q_lock[0] = this->_q_lock[1] = this->_q_lock[2] = this->_q_lock[3] = -1;
  10. #endif
  11.         _q_value = value;
  12.     }
  13. ...
  14.     // Non-atomic API
  15.     inline bool operator==(int value) const
  16.     {
  17.         return _q_value == value;
  18.     }
  19.  
  20.     inline bool operator!=(int value) const
  21.     {
  22.         return _q_value != value;
  23.     }
  24.  
  25.     inline bool operator!() const
  26.     {
  27.         return _q_value == 0;
  28.     }
  29.  
  30.     inline operator int() const
  31.     {
  32.         return _q_value;
  33.     }

 Signature 

QT - Apple QuickTime
Qt - Nokia’s Qt Development Frameworks
Apple is a competitor of Nokia, so QT != Qt

10 replies

June 10, 2010

Jorj Jorj
Lab Rat
97 posts

The fetch and store command set, will set the value of the int atomically, it will just also return the value atomically.

To retrieve the int without setting it, may be trickier, it has an int conversion operator, but i am not sure if this is an atomic action This seems to be the only command to get the value without changing it though, although if the code is actually:

  1. inline operator int() const
  2. {
  3.     return _q_value;
  4. }

Then it should be atomic right??? (I’m not an expert in this area, but an inline function that returns a member should only be one operation right?)

June 10, 2010

SABROG SABROG
Lab Rat
82 posts

But why boost use memory barrier?

  1. // Rational for the implementation of the atomic read and write functions.
  2. //
  3. // 1. The Alpha Architecture Handbook requires that access to a byte,
  4. // an aligned word, an aligned longword, or an aligned quadword is
  5. // atomic. (See 'Alpha Architecture Handbook', version 4, chapter 5.2.2.)
  6. //
  7. // 2. The CXX User's Guide states that volatile quantities are accessed
  8. // with single assembler instructions, and that a compilation error
  9. // occurs when declaring a quantity as volatile which is not properly
  10. // aligned.
  11.  
  12. //! Atomically read an boost::uint32_t from memory
  13. //! Acquire, memory barrier after load.
  14. inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
  15. {  boost::uint32_t old_val = *mem; __MB(); return old_val;  }
  16.  
  17. //! Atomically set an boost::uint32_t in memory
  18. //! "mem": pointer to the object
  19. //! "param": val value that the object will assume
  20. //! Release, memory barrier before store.
  21. inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
  22. {  __MB(); *mem = val; }

 Signature 

QT - Apple QuickTime
Qt - Nokia’s Qt Development Frameworks
Apple is a competitor of Nokia, so QT != Qt

June 10, 2010

SABROG SABROG
Lab Rat
82 posts

Or why QAtomicInt doesn’t support memory order models for load and store operations like this:

  1. mutex.store(0, std::memory_order_release);
  2. mutex.store(0, std::memory_order_relaxed);
  3. s->head($).load(rl::memory_order_relaxed);
  4. local_count_.load(std::memory_order_acquire)

 Signature 

QT - Apple QuickTime
Qt - Nokia’s Qt Development Frameworks
Apple is a competitor of Nokia, so QT != Qt

July 4, 2010

ixSci ixSci
Lab Rat
203 posts

SABROG, are you sure you’ve read documentation properly?

  1. int fetchAndAddAcquire ( int valueToAdd )
  2. int fetchAndAddOrdered ( int valueToAdd )
  3. int fetchAndAddRelaxed ( int valueToAdd )
  4. int fetchAndAddRelease ( int valueToAdd )
  5. int fetchAndStoreAcquire ( int newValue )
  6. int fetchAndStoreOrdered ( int newValue )
  7. int fetchAndStoreRelaxed ( int newValue )
  8. int fetchAndStoreRelease ( int newValue )
  9. bool ref ()
  10. bool testAndSetAcquire ( int expectedValue, int newValue )
  11. bool testAndSetOrdered ( int expectedValue, int newValue )
  12. bool testAndSetRelaxed ( int expectedValue, int newValue )
  13. bool testAndSetRelease ( int expectedValue, int newValue )

Those functions do all you asked for, if I’ve understood you correctly.

July 5, 2010

Jorj Jorj
Lab Rat
97 posts

Yes, im with ixSci.

July 5, 2010

SABROG SABROG
Lab Rat
82 posts

fetchAndStore* on my IA-32 simple xchg instruction. Atomic load on IA-32 must be ordinary “mov” with memory fence/barrier, on PowerPC – “ld” instruction. xchg slower than mov.

 Signature 

QT - Apple QuickTime
Qt - Nokia’s Qt Development Frameworks
Apple is a competitor of Nokia, so QT != Qt

July 5, 2010

ixSci ixSci
Lab Rat
203 posts

SABROG, I don’t understand you. XCHG is an atomic instruction. Thus it is exactly things your are searching for, isn’t it?
About perfomance: Do you really think you would have noticeable overheads with using XCHG instead of MOV?

Atomic load on IA-32 must be ordinary “mov” with memory fence/barrier, on PowerPC – “ld” instruction.

Why do you think so? XCHG has lock mechanism inside itself, but MOV doesn’t.

July 5, 2010

SABROG SABROG
Lab Rat
82 posts
ixSci wrote:
About perfomance: Do you really think you would have noticeable overheads with using XCHG instead of MOV? XCHG has lock mechanism inside itself, but MOV doesn&#39;t.

MOV is atomic for 8, 16, 32 bits variables with ordering memory on IA-32. I write call_once() function implementation on Qt with QAtomicInt class and my implementation slower than std::call_once() in 9 times. I use callgrind and found what problem in atomic operations like fetchAndStore()/testAndSet(). For test perfomance i remove all atomic operations and write native C++ code, only after this i get identical perfomance like with std::call_once.

 Signature 

QT - Apple QuickTime
Qt - Nokia’s Qt Development Frameworks
Apple is a competitor of Nokia, so QT != Qt

July 5, 2010

ixSci ixSci
Lab Rat
203 posts

I don’t know what is in the guts of std::call_once, but Qt uses lock and it’s a very heavy instruction(relative to other). Superficial analysis of Bing output show no implementations of the atomic read\write with mov. But all were with XCHG using. If you’re using x86 it should be overkill to struggle for each CPU tick, though. Could you explain why you count each CPU tick and what the “9 times” would be in the time scale, please?
Also, I think you deepening in the premature optimization. But if you have such an insistence to have faster atomic operation why don’t you use original C++0x(11 I hope) in your code? It would be uglier a little but you will have all that you want.

BTW, Windows atomic operations also use XCHG under the hood(if Bing doesn’t lie to me.)

July 6, 2010

SABROG SABROG
Lab Rat
82 posts

ixSci wrote:
Could you explain why you count each CPU tick and what the “9 times” would be in the time scale, please?

1 second on 1 billion calls std::call_once versus 9 seconds with Qt atomic implementation.

ixSci wrote:

Also, I think you deepening in the premature optimization. But if you have such an insistence to have faster atomic operation why don&#39;t you use original C++0x(11 I hope) in your code? It would be uglier a little but you will have all that you want.

I don’t want people to say, what Qt library slower than standard library or BOOST.

 Signature 

QT - Apple QuickTime
Qt - Nokia’s Qt Development Frameworks
Apple is a competitor of Nokia, so QT != Qt

 
  ‹‹ QPixmap VS QImage, X server problem      Q_GLOBAL_STATIC is reentrance now? ››

You must log in to post a reply. Not a member yet? Register here!