Share via


Performance of lock() vs. Interlocked.CompareExchange()

Question

Sunday, November 21, 2010 10:21 AM

We have an analytical application which runs a bunch of tasks in parallel. For the most part the tasks do not need to modify any shared data, but there is one exception, which causing us some headache.   

Basically all the tasks need to perform some adds into an array of doubles, like this:

 

m_sharedData[i][j] += number;

 

We have tried two different ways protecting the shared data:

 

lock(m_lock)

{

  m_sharedData[i][j] += number;

}

 

And

 

double oldVal;

double unChangedVal;

do

{

  oldVal = m_sharedData[i][j];

  unChangedVal = Interlocked.CompareExchange(ref m_sharedData[i][j], oldVal + val, oldVal);

}

while (unChangedVal != oldVal);

 

A few things to know:

 

This code is in the innermost loop and to will be called very frequently. A typical analysis takes about an hour and that may generate something like 50 billion calls to this code.

 

On the other hand: There is a significant memory overhead for each task, so we do not run any more tasks than there are CPU-cores on the system, so on a pretty big box something like 24 tasks/threads, and m_sharedData will typically have something like 20000 to 100000 elements, so in many cases it will only be a (relatively) rare occurrence that two threads hit the same array-element at the same time.

 

The parallelism is introduced with a .net 4 parallel loop:

 

var options = new ParallelOptions { MaxDegreeOfParallelism = m_numberOfThreads };

Parallel.ForEach(GetJobs(), options, DoWork);     

 

There will typically be around 1000 Jobs to run. The entire ForEach-operation will take about 5 seconds to complete (with 24 CPU-cores). (We get to a full hour since there is an outer loop around this.)

 

We were expecting the CompareExchange-version to clearly outperform the lock-version of the code, but that is not what we see.  In fact, CompareExchange seems to be anywhere from 30 to 300 % slower that lock.

 

We’ve wanted to measure how frequently two threads hit the same array element at the same time and we came across a performance counter: Contention Rate / sec in the .NET CLR LocksAndThreads category, but I am not sure that we can trust it? In some situations (where we do run with the lock version of the code, this counter just gives 0 contentions over extended periods of time. That’s strange to me.

All replies (3)

Wednesday, November 24, 2010 2:06 AM ✅Answered

Hi ThomasIsr,

When multiple threads access shared data, that data must be accessed in a thread-safe way. The fastest way to manipulate data in a thread-safe way is to use the interlocked family of methods. Lock method will call a Monitor.Enter(Object) and Monitor.Exit() in System.Threading.Monitor Class to mark if the current object has been locked or unlocked. So Lock’s performance should be slower than Interlocked.

But I think your case wasn’t a simple issue. If the logic of lock method is simple but Interlocked is very complex, the duration of lock’s performance is certainly less than Interlocked one. If in your project lock ’s performance is better than Interlocked method, I would recommend that you can accept lock method in your project.

According to your provided code snippets, there is a while loop in the Interlocked method. Is there a same loop or condition in the lock method? I don’t ensure it. So could you please provide some entire code snippets which can be reproduced in Visual Studio?

Regards,

Larcolais

Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.


Wednesday, November 24, 2010 6:19 AM ✅Answered

Hi,

Please Refer below link, may be it is useful,

http://blog.moxen.us/2010/08/22/lock-spinlock-and-compareexchange-performance/

http://social.msdn.microsoft.com/Forums/en-US/clr/thread/e68f94c1-5677-45ee-9511-7a49a892323f

Regards,

S.Subashselvan.


Tuesday, November 23, 2010 5:04 AM

Obviously, Interlocked.Exchange is better than lock(). It is faster.

Ester