lock-free calc: how to sum N double numbers that are changing by other threads?

◇◆丶佛笑我妖孽 提交于 2019-12-09 07:30:28

I think you might get better performance and clearer code if you do not use an extra thread and loop for your sum. On every change to an instrument you calculate the difference and immediately update the index and perform the notify

So if a thread calls InstrumentUpdated for a single instrument;

  change = newvalue - currentvalue;
  // used interlocked here to change the index threadsafe
  StockExchangeSum = Interlocked.Add(ref StockExchangeSum,change);
  NotifyIndexChanged();

Can double[] be a more complex type? How does WaitHandle.WaitAny compare performance wise?

Something like as follows.

private Index[] indicies;

public class Index
{
    public WaitHandle Updated =
        new EventWaitHandle(false, EventResetMode.AutoReset);
    public double _value;
    public double Value
    {
        get {return _value;}
        set
        {
            if(_value != value)
            {
                _value = value;
                Updated.Set();
            }
        }
    }
}

TaskFactory.StartNew(() =>
{
    while(true)
    {
        WaitHandle.Any(indicies.Select(i => i.Updated));
        CalculateAndNotify();
    }
});

Some points for you to think about

  • Have you tried profiling your calculation block in isolation to the rest of the code? I noticed this in your Calculate function:

    for (int i = 0; i < _instrumentIds.Count(); i++)

    _instrumentIds.Count() invokes an iteration over the entire collection and it is possible this is invoked for each trip around the loop. i.e. you are doing N^2/2 iterations of _instrumentIds

  • Is the _instrumentIdsIEnumerable being modified during this calculation operation? If so you could get all sorts of race conditions leading to incorrect answers.

  • Is the Task containing CalculateAndNotify called once or is it called many times (nested)? E.g. is there some operation inside CalculateAndNotify that could cause it to be triggered recursively?

    If so, you might find you have several calculations performing simultaneously (using more than one thread until the pool is starved). Can you include some logging on start/end of operation and perhaps count the number of simultaneous calculations to check this?

    If this is an issue you could include some logic whereby the CalculateAndNotify operation is queued up and new calculate operations cannot be executed until the previous has completed.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!