4

Do you know any parallel modified moving average algorithm?

I want quickly calculate moving average but not with sequential algorithms. I want use parallel algorithms but I have still not found solution.

The best algorithm which I found is sequential algorithm modified moving average for measuring computer performance:

new_avg =  alfa(new_time, previous_time) * new_value + (1-alfa(new_time, previous_time)) * previous_avg

alfa(new_time, previous_time) = 1- exp(-(new_time - previous_time)/moving_period)

Some other algorithms are good also but I have not found parallel algorithms.

It is hard question and I need some help with it.

Consider that I want count events that will come in random time order - early events can come later that late events - you could assume that early event can be skipped/become obsolete after processing late events (or with some timeout). Not assume sequential time order of events and that event from same time will come with same time.


I do not want use any algorithm which require to remember many samples (especially all) it should only remember time and previous average value maybe some additional value but not all or same samples. Consider that algorithm can make some minor errors not need to be perfect if reason of it is some performance boost.

It will be very nice if it will use sharding but not required.

Chameleon
  • 9,722
  • 16
  • 65
  • 127

2 Answers2

5

A moving average where events arrive in sequence could be done like this:

newMovingAverage = ((MovingAverage * (n - 1)) + newSample) / n

where n dictates how big (or little) influence this sample should have on the moving average. The greater the n, the smaller the influence. Over time, older samples will have less and less influence on the moving average as new samples arrive.

With samples coming out of sequence you can try to mimic that behavioral by letting the age of the sample dictate how much influence it should have on the moving average. This could e.g. be done like this:

influence = (1 + sampleAge)^2 * n 
newMovingAverage = ((MovingAverage * (influence - 1)) + newSample) / influence 

Where I let the sampleAge dictate how much the newSample should influence the moving average.

Shadow The GPT Wizard
  • 66,030
  • 26
  • 140
  • 208
Ebbe M. Pedersen
  • 7,250
  • 3
  • 27
  • 47
  • Very good idea with influence depending on time (i.e. linear or better exponential)! It will allow some wages depending on **counter now** and **sample now**. Not sure about **sampleAge** what you mean by this value can you explain it (since 30s will lead to 32^2 & n - If think you do hidden assumption that data coming in cycle and **sampleAge** is order number whatever order and number of samples is not know since parallel)? Simple moving average will not work since not depend on time - this formula has **hard and hidden assumption** that samples is read with some period/cycle. – Chameleon May 08 '13 at 07:38
  • 1
    I'm not sure how fast the effect of an old sample should wear off. Above I have based it on time, but it could as well be based on another way of measuring how old the sample is. You might keep track of how many samples you have within a period, and then try to estimate how far back in the sequence a sample might be. – Ebbe M. Pedersen May 08 '13 at 08:28
  • I think that I found solution by your suggestion and it is parallel solution - it is for frequency counting (x=1 in this case). Consider this formula which you suggest: newAvg = x1 + (1 - alfa) * oldAvg (alfa = 1 - exp(timeDelta/period). If sample is missed it is not problem since you can calculate alfa backward and use fixedAvg = notFixedAvg + (1 - alfa) * x2 (you will wear off since = (1 - alfa) * oldAvg = (1 - alfa) * (x1 + **x2**)). I was use rule a*d + b*d = (a+b)*d. Good hit many times lead to solution. What you think about it? – Chameleon May 08 '13 at 11:40
  • Exactly how it should be applied backwards properly depends on the data set in question. If it works for you it properly is the right solution :) Glad that you could use the general idea. – Ebbe M. Pedersen May 08 '13 at 13:58
4

The possibility of having a parallel algorithm would depend on the nature of the moving average that you are using.

The algorithm that you show in your question is an exponential smoother. Thus, the first value of the data has an influence on every calculated average value. The amount of influence that the first value has decreases with every new data point, but even the last average in the sequence will be slightly influenced by the first data point.

This sort of moving average can't be parallelised because you can't calculate any average without using (explicitly or implicitly) all the previous data that has been received.

However, Wikipedia's article on moving averages nicely summarises a range of moving average methods, some of which are easily implemented in parallel.

For example, a simple moving average takes the following form (for odd n)**:

n2 = int(n/2)
moving_average[i] = (data[i-n2] + data[i-n2+1] ... + 
    data[i] + ... + data[i+n2-1] + data[i+n2])/n

This method doesn't make use of any data earlier than int(n/2) points before i to calculate the moving average at point i. Therefore, you could calculate the moving average of a data set of m items in parallel with p threads by dividing the m items into p sub-sequences, each of which overlaps the next and previous (excepting the first and last sub-sequences) sub-sequence by int(n/2) data points, and have each thread calculate the moving averages for its sub-sequence.

You can find an efficient sequential implementation of this algorithm (which would be applicable to each thread of the parallel implementation) in the question Simple Moving Average summation/offset issue and its answer. That method calculates a trailing moving average rather than the (arguably preferred) centrally-located moving average that I've shown above. That is, it puts the value that I calculated above at moving_average[i+n2] instead of at moving_average[i].

** This leaves aside the possibility that the data may be at irregular time intervals. The method you've shown addresses that issue and it can be dealt with the same way in other methods.

Community
  • 1
  • 1
Simon
  • 10,679
  • 1
  • 30
  • 44
  • I will study more this algorithm. You have right that _exponential smoother_ works in such way that next result depend on previous change so all values is locked by chain - if I will skip one value whole chain need to be calculated from start. – Chameleon May 07 '13 at 21:43