Вектор смещения в тяге
Я смотрю на проект, связанный с онлайн (потоковым) данными. Я хочу работать со скользящим окном этих данных. Например, скажем, что я хочу хранить 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;