Вектор смещения в тяге

Я смотрю на проект, связанный с онлайн (потоковым) данными. Я хочу работать со скользящим окном этих данных. Например, скажем, что я хочу хранить 10 значений в моем векторе. Когда приходит значение 11, я хочу сбросить значение 1, переместить все заново, а затем поместить значение 11 там, где было значение 10.

Долгий путь будет примерно таким:

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;

Есть ли "быстрый" способ сделать это с помощью тяги? Проект, на который я смотрю, будет иметь около 500 векторов, которые будут выполнять эту операцию одновременно.

Спасибо!

3 ответа

Решение

Как я уже сказал, кольцевой буфер - это то, что вам нужно. Нет необходимости сдвигать туда, только один счетчик и массив фиксированного размера.

Давайте подумаем, как мы можем справиться с 500 кольцевыми буферами.

Если вы хотите иметь 500 (пусть это будет 512) скользящих окон и обрабатывать их все на GPU, то вы можете упаковать их в одну большую 2D-текстуру, где каждый столбец представляет собой массив выборок на один и тот же момент.

Если вы получаете новые образцы для каждого вектора одновременно (я имею в виду один новый образец для каждых 512 буферов на одном шаге обработки), тогда эту "кольцевую текстуру" (например, цилиндр) необходимо обновить только один раз (загрузить массив новых образцов на каждом шаге) и вам нужен только один счетчик.

Я настоятельно рекомендую использовать другую, но все еще бесплатную библиотеку для этой проблемы. В 4 строках кода ArrayFire вы можете сделать все 500 векторов следующим образом:

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

Я сравнил код Thrust с тем же самым, и ArrayFire ускоряется в 10 раз по сравнению с Thrust.

Недостатком является то, что ArrayFire не является открытым исходным кодом, но он все еще бесплатен для такого рода проблем.

Хочешь хочешь просто thrust::copy, Вы не можете выполнять сдвиг на месте параллельно, потому что вы не можете гарантировать, что значение прочитано до того, как оно будет записано.

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;
Другие вопросы по тегам