1

I'm looking at a project involving online (streaming) data. I want to work with a sliding window of that data. For example, say that I want to hold 10 values in my vector. When value 11 comes in, I want to drop value 1, shift everything over, and then place value 11 where value 10 was.

The long way would be something like the following:

int n = 9;
thrust::device_vector<float> val;
val.resize(n+1,0);

// Shift left
for(int i=0; i != n-1; i++){
   val[i] = val[i+1];
}

// add the new value to the last position
val[n] = newValue;

Is there a "fast" way to do this with thrust? The project I'm looking at will have around 500 vectors that will need this operation done simultaneously.

Thanks!

Sergey K.
  • 24,894
  • 13
  • 106
  • 174
Noah
  • 567
  • 8
  • 19
  • 2
    [Ring buffer](http://en.wikipedia.org/wiki/Ring_buffer) is what you need. No need to shift there, only one counter and a fixed size array. – Viktor Latypov Jul 02 '12 at 20:41
  • @Viktor. That's **exactly** what I need!! Perfect. Now, the big question is if I can do this with device vectors in thrust? I'd prefer to keep the buffer/vector on the GPU. Thoughts? – Noah Jul 03 '12 at 01:10

3 Answers3

3

As I have said, Ring buffer is what you need. No need to shift there, only one counter and a fixed size array.

Let's think how we may deal with 500 of ring buffers.

If you want to have 500 (let it be 512) sliding windows and process them all on the GPU, then you might pack them into one big 2D texture, where each column is an array of samples for the same moment.

If you're getting new samples for each of the vector at once (I mean one new sample for each 512 buffers at one processing step), then this "ring texture" (like a cylinder) only needs to be updated once (upload the array of new samples at each step) and you need just one counter.

Viktor Latypov
  • 14,289
  • 3
  • 40
  • 55
  • 1
    The OP wants help with using Thrust to do what he asks. – harrism Jul 03 '12 at 12:29
  • Not "married" to thrust, but its currently the only way I know to code for a GPU. – Noah Jul 03 '12 at 22:13
  • I only meant that the "best way to copy" is to avoid copying if possible. No matter what technology is used. A single counter is better than the need to shift the whole array (or 500 in your case) – Viktor Latypov Jul 03 '12 at 22:21
2

I highly recommend using a different, yet still free, library for this problem. In 4 lines of ArrayFire code, you can do all 500 vectors, as follows:

array val = array(window_width, num_vectors);
val = shift(val, 0, 1);
array newValue = array(1,num_vectors);
val(span,end) = newValue;

I benchmarked against Thrust code for the same and ArrayFire is getting about a 10X speedup over Thrust.

Downside is that ArrayFire is not open source, but it is still free for this sort of problem.

Ben Stewart
  • 311
  • 1
  • 5
  • Hey, if you're gonna downvote, at least pony up your reasons. Is something I said wrong? @Noah has already said he's not married to Thrust. – Ben Stewart Jul 04 '12 at 01:44
  • VERY VERY interesting suggestion. I'm not married to thrust, and the ArrayFire library looks interesting. I plan to do some reading up on this tonight. Thanks! – Noah Jul 04 '12 at 04:07
1

Want you want is simply thrust::copy. You can't do a shift in place in parallel, because you can't guarantee a value is read before it is written.

int n = 9;
thrust::device_vector<float> val_in(n);
thrust::device_vector<float> val_out(n+1);

thrust::copy(val_in.begin() + 1, val_in.end(), val_out.begin());

// add the new value to the last position
val_out[n] = newValue;
harrism
  • 26,505
  • 2
  • 57
  • 88
  • Thanks for the suggested code. However, the copying from val_in to val_out at each time step seems excessive. – Noah Jul 03 '12 at 21:42
  • 1
    If you want to physically shift the data, it has to be copied (your loop does a copy)! And if you want that done in parallel, it cannot correctly be done in-place so you need two buffers. If you don't actually want to physically shift, then you could implement a counter-based ring buffer as Viktor suggests, but you will have to maintain this counter outside of your Thrust code. – harrism Jul 04 '12 at 01:01