锁无关计算:如何总结由其他线程将N-双号? [英] lock-free calc: how to sum N double numbers that are changing by other threads?

查看:152
本文介绍了锁无关计算:如何总结由其他线程将N-双号?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

UPD:让我改一下我的问题很快。
有N个双数。有N专用线程他们每个人更新自己的双号( _cachedProduct 在下面的例子)。

upd: Let me rephrase my question shortly. There are N double numbers. There are N dedicated threads each of them update own double number (_cachedProduct in the example below).

不知怎的,我需要有这些数字,我需要 IndexUpdated 来的双号被更改后,(它可以尽快引发的事件将是很好,如果这样的事件可以在10微秒或更少)得到提升。

Somehow I need to have sum of these numbers and I need IndexUpdated event to be raised ASAP after any double number is changed (it would be nice if such event can be raised in 10 µs or less).

下面是我试图执行这个任务。

Below is how I tried to implement this task

============================================= ==

===============================================

要计算我创建私人双重[] _cachedProduct证券交易所指数; 字段。这些字段由多个线程写入

To calculate stock exchange index I create private double[] _cachedProduct; field. These field is written by many threads

    // called from another threads
    public override void InstrumentUpdated(Instrument instrument)
    {
        if (!_initialized)
        {
            if (!Initialize())
            {
                return;
            }
        }
        int instrumentId = instrument.Id;
        OrderBook ob = Program.market.OrderBook(instrument);
        if (ob.MedianOrAskOrBid == null)
        {
            _cachedProduct[instrumentId] = 0;
        }
        else
        {
            _cachedProduct[instrumentId] = ((double) ob.MedianOrAskOrBid)*_ammounts[instrumentId];
        }
    }



_ammounts 是预初始化数组,并请忽略初始化方法和变量 - 他们只是工作

_ammounts is pre-initialized array and please ignore Initialize method and variable - they just works.

在循环我只是总结所有_cachedProduct和价值观念的变化,当我通知别人

In loop I just sum all _cachedProduct and when values changes I notify others.

        Task.Factory.StartNew(() =>
                {
                    while(true)
                    {
                        if (_initialized)
                        {
                            break;
                        }
                    }
                    while (true)
                    {
                        CalculateAndNotify();
                        //Thread.Sleep(5);
                    }
                }
            , TaskCreationOptions.LongRunning);


    protected void CalculateAndNotify()
    {
        var oldValue = Value;
        Calculate();
        if (oldValue != Value)
        {
            NotifyIndexChanged();
        } 
    }

    protected override void Calculate()
    {
        double result = 0;
        for (int i = 0; i < _instrumentIds.Count(); i++)
        {
            int instrumentId = _instrumentIds[i];
            if (_cachedProduct[instrumentId] == 0)
            {
                Value = null;
                return;
            }
            result += _cachedProduct[instrumentId];;
        }
        Value = result;
    }



我必须使用互锁更新我的双 _cachedProduct 的值,但现在请无视这一事实,你看到了什么其他的问题与此代码?

I must use Interlocked to update my double _cachedProduct values but please ignore that fact now, what other problems with this code do you see?

我应该叫计算方法,而(真)所以我总是使用一个核心无延迟。没有我的机器有24个内核,所以我想这是确定的。

Should I call Calculate method inside while(true) so I always use one core without delays. My machine has 24 cores so I was thinking this is ok.

然而 Thread.sleep代码(5)(评论)我确实看到整体方案显著放缓,我不明白为什么。程序执行在很多地方要慢几十倍。

However without Thread.Sleep(5) (commented) I do see significant slow-down in the program overall and I do not understand why. Program executes several dozens times slower in many places.

现在的问题是,如果我使用的想法,而(真)在没有任何都锁定是确定。或者我应该介绍一些锁定的方法,所以我只会计算时的一个 _cachedProduct 更新指标?

The question is if my idea of using while(true) without any locking at all is OK. Or should I introduce some locking method so I would only Calculate index when one of of _cachedProduct is updated?

推荐答案

我想,如果你不使用你的总和一个额外的线程,循环可能会获得更好的性能和更清晰的代码。在每一个变化的仪器,你计算的差异,并立即更新索引并执行通知

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

所以,如果一个线程调用InstrumentUpdated为一台仪器;

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();

这篇关于锁无关计算:如何总结由其他线程将N-双号?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆