Concurrency Runtime: spinlock ?
-
Dienstag, 10. April 2012 16:56
Hi,
Is there any kind of spinlock (a very lightweight critical_section, optimized for locking during short periods of time) in the concurrency runtime ?
Best regards, Arnaud.
Alle Antworten
-
Mittwoch, 11. April 2012 04:11
Could you roll your own using try_lock?
Concurrency::critical_section cs;
while ( !cs.try_lock() ) // spin:
; -
Mittwoch, 11. April 2012 13:16
Thanks Joe,
Great hint. Tried that but found in my case that the solution here (http://www.codeproject.com/Articles/184046/Spin-Lock-in-C) provides an overall 20% performance increase over the Concurrency::critical_section::lock() and your spinlock (VS11 beta, x64).
Maybe some adjustments could be done in the current try_lock() implementation to achieve the same performance level ???
I found other spinlock implementations but did not try them:
- the one in the .Net Framework 2.0 here: http://www.koders.com/cpp/fidD3FB067877521C26AC39D985B687ECB255D1A6DA.aspx
- another one on CodeProject: http://www.codeproject.com/Articles/784/User-Level-Spin-Locks
- a proof-of concept on Wikipedia: http://en.wikipedia.org/wiki/SpinlockI cannot assert the correctness of the implementation provided on CodeProject, neither its fairness or compatibility with the Concurrency Runtime. Could you ?
All the best, Arnaud.
- Bearbeitet Arnaud Faucher Mittwoch, 11. April 2012 13:19 links
-
Mittwoch, 11. April 2012 20:58
The concrt.h file contains classes like:
- Concurrency::details::_SpinLock
- Concurrency::details::_SpinWait
- Concurrency::details::_ReentrantBlockingLock
- Concurrency::details::_NonReentrantBlockingLock
Are these classes intended for the private use of the Concurrency Runtime current implementation (ie. undocumented features), or can we rely on these classes to build applications?
Best regards, Arnaud.
-
Donnerstag, 12. April 2012 00:34Besitzer
Hello,
Re: supporting something out of the box.
For pure spin locks, you can simply use the Windows API InitializeCriticalSectionAndSpinCount() with a high spin count. http://msdn.microsoft.com/en-us/library/windows/desktop/ms683476(v=vs.85).aspx
Re: hand rolled spin lock in codeproject
While the logic seems ok, there are always nuances to worry about while implementing a lock. In the codeproject link you sent, see the discussion section (my vote is 2).
Re: is this safe to use in ConcRT.
The logic is straightforward and thread simply spins. So there is no need for spin locks to be ConcRT aware.
Re: details namespace.
Yes, they are private classes for internal implementation support. So they are unsupported for use in applications.
Re: performance
The issue is whether you see this performance gain consistently, across a variety of workloads/applications using many locks, and on scalable hardware (32 cores?). Many implementors of locks end up choosing to spin for a bit and then actually do kernel level block. That way, it can capture best of both worlds.
Hope this helps! :)
Rahul V. Patil
- Als Antwort vorgeschlagen DanielMothMicrosoft Employee, Owner Donnerstag, 12. April 2012 01:13
- Als Antwort markiert Arnaud Faucher Donnerstag, 12. April 2012 18:24
-
Donnerstag, 12. April 2012 04:23
Hi Arnaud. I was trying to stay within the Concurrency Runtime for a solution (or the new C++11 standard). The use of try_lock was the best I could come up with --- you did some good detective work to find other solutions, including privates functions in concrt.h (which I would not use) and the solutions on CodeProject. I believe the one you found here (http://www.codeproject.com/Articles/184046/Spin-Lock-in-C) is good, though I would take a look at the mentioned revisions and use the latest code (e.g. revision 3 using interlockedExchange in release() method).
But if you're willing to leave the Concurrency RT, I would also investigate Rahul's suggestion of calling the Windows API directly: "For pure spin locks, you can simply use the Windows API InitializeCriticalSectionAndSpinCount() with a high spin count.http://msdn.microsoft.com/en-us/library/windows/desktop/ms683476(v=vs.85).aspx." I suspect the OS will offer the most efficient solution...
If you can, please report back, I'm curious which approach turns out to be most efficient. Cheers,
-
Donnerstag, 12. April 2012 13:23
Hi Joe and Rahul,
Here are the results. As per your suggestions, I finally ended up with the following wrapper:
#include <Windows.h> class spinlock { private: CRITICAL_SECTION _cs; spinlock(const spinlock&); spinlock& operator=(const spinlock&); public: spinlock(unsigned int spinCount = 4000U) // RAII { if (!InitializeCriticalSectionAndSpinCount(&_cs, spinCount)) throw std::exception("Could not initialize spinlock"); } ~spinlock() { DeleteCriticalSection(&_cs); } void lock() { EnterCriticalSection(&_cs); } bool try_lock() { return TryEnterCriticalSection(&_cs); } void unlock() { LeaveCriticalSection(&_cs); } };My case is very appropriate for the use of a spinlock: very small code block (6 float additions), very frequently called, rare contention situations.
I'll finally opt for the spinlock class above above because it gives performances similar to sameer_87's code on CodeProject, but with more straightforward Windows APIs.
All the best and thanks for your feedback, Arnaud.
- Als Antwort vorgeschlagen Rahul V. PatilModerator Donnerstag, 12. April 2012 17:24
- Als Antwort markiert Arnaud Faucher Donnerstag, 12. April 2012 18:24

