Moving average implementation

86 views
Skip to first unread message

Muneer

unread,
Mar 30, 2015, 5:51:56 AM3/30/15
to arrayfi...@googlegroups.com
Hi guys,

I've been struggling for the past couple of days trying to implement a moving average in ArrayFire. I've simplified the code as much as I could to explain it:

#include <arrayfire.h>


using namespace af;


array ma
(array data, array window)
{
   
const int w = window.scalar<int>();
   
return (data.rows(w, end) - data.rows(0, end-w))/w;
}


int main()
{
    array data
= randu(10, 3);
    array data_accum
= accum(data);

    af_print
(data);
    af_print
(data_accum);


   
// Generate 4 random window sizes from 1-10
    array windows
= randu(4, 1, s32) % 10;
    af_print
(windows);


    array avg
= ma(data_accum, windows);
    af_print
(avg);


   
return 0;
}

Essentially I'm trying to get an array of moving averages using different window sizes. At the moment the answer I'm getting is wrong. I tried using gfor, but I struggled a lot trying to get the seq indexing to work with my example. I can do it with a for loop but I need this to run really really really fast. Ideally I'm also looking to get rid of the .scalar() call in the ma() function too.. Intuitively I believe it should be possible.

How do I get this working and running really fast?

Kind regards,
Muneer


Pavan Yalamanchili

unread,
Mar 30, 2015, 5:09:07 PM3/30/15
to Muneer, arrayfi...@googlegroups.com
Hi Muneer,

I am not entirely sure if I understand the problem correctly, but I think this is what you need.

array rng = range(10) + 1;
array avg_accum = data_accum / rng;
af_print(avg_accum);
af_print(avg_accum(windows));

--
You received this message because you are subscribed to the Google Groups "ArrayFire Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to arrayfire-use...@googlegroups.com.
To post to this group, send email to arrayfi...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/arrayfire-users/5827398a-37c9-45cf-a3a8-67f94a527497%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Pavan Yalamanchili

unread,
Mar 30, 2015, 5:11:01 PM3/30/15
to Muneer, arrayfi...@googlegroups.com
Oops, you may need to do another step:

array avg_moving = diff1(join(constant(0, 1, 1, avg_accum.type()), avg_accum)));

Pavan Yalamanchili

unread,
Mar 30, 2015, 5:17:53 PM3/30/15
to Muneer, arrayfi...@googlegroups.com
ACtually its buggy. Give me some time to figure this out.

Pavan Yalamanchili

unread,
Mar 30, 2015, 5:23:23 PM3/30/15
to Muneer, arrayfi...@googlegroups.com
Having different window sizes is going to be hard to do in parallel. For a single window size, it is a simple convolution.

What are the typical number of winodws you are looking at ?

Muneer

unread,
Mar 31, 2015, 10:59:39 AM3/31/15
to arrayfi...@googlegroups.com, mun....@gmail.com
Hi, thanks very much for having a look at this :-)

For moving averages in particular I'd be using windows in the range of 1-200. I'll likely be needing about 90%+ of those to be calculated. The data always stays the same throughout the program run (~90k rows 1D).

I agree I can do it in O(n) by a GPU call per window size in for loop over the unique window sizes. Was really hoping I could do this in constant time though..

The reason this design is so important to me is because I'll be using lots of different formulas, ie. not just moving averages. However they are all based on the concept of calculation over different moving window periods. So there will be many for loops in my code (one for each formula) if I go down the for loop route, which I'm trying to avoid..

Does ArrayFire support asynchronous evaluation? eg. If perhaps I gave ArrayFire a semaphore in the .eval(), it could increment it and return immediately (executing in the background).. then I can keep piling more work onto it and then wait for the results at the end with a .sync(semaphore) or something?

I guess I could write a caching class that lazy evaluates the formula / window combination I'm requesting in the code and keeps the result in host memory. Could also pre-calculate the entire formula / window combinations space and read those numbers from disk when I load the data. It will be a big cache, but I can do it on EC2.

What would be the best way to do this different windows implementation?

Pavan Yalamanchili

unread,
Mar 31, 2015, 11:05:46 AM3/31/15
to Muneer, arrayfi...@googlegroups.com
Hi,

ArrayFire is non blocking but it is not asynchronous currently. We are thinking of ways to make this happen. Please follow this issue for more details:

> For moving averages in particular I'd be using windows in the range of 1-200. I'll likely be needing about 90%+ of those to be calculated. The data always stays the same throughout the program run (~90k rows 1D).

Does that mean the data is 90K rows x 1 column? If that is the case then we can pad the convolution windows with zeros to generate windows of the same size. All of the operations can then be done in parallel.

--
Pavan



Muneer

unread,
Mar 31, 2015, 11:24:14 AM3/31/15
to arrayfi...@googlegroups.com, mun....@gmail.com
Yes it's 90k rows x 1 column

I'm not sure how to pad the window sizes and convolve them to produce the result.. Please could you demonstrate how it looks in code?

Pavan Yalamanchili

unread,
Mar 31, 2015, 11:46:55 AM3/31/15
to Muneer, arrayfi...@googlegroups.com
Hi Muneer,

You can look at the code here for an example: https://gist.github.com/pavanky/167a4f60089d0dcd6d3d

At the boundaries, I assumed "0" for the missing pieces. We can probably change that to match what you want.

Muneer

unread,
Mar 31, 2015, 11:58:46 AM3/31/15
to arrayfi...@googlegroups.com, mun....@gmail.com
ahh I see what you've done here! That's a very clever solution. Thank you so much for your help :-)

Pavan Yalamanchili

unread,
Mar 31, 2015, 12:12:02 PM3/31/15
to Muneer, arrayfi...@googlegroups.com
Hi Muneer,

The windows need to be centered properly to get the right results. I am working on updating the gist. I will let you know when it is fixed.

Reply all
Reply to author
Forward
0 new messages