Векторизирайте кода на matlab, за да картографирате най-близките стойности в два масива

Имам два списъка с времеви марки и се опитвам да създам карта между тях, която използва imu_ts като истинско време и се опитва да намери най-близката стойност на vicon_ts до него. Резултатът е 3xd матрица, където първият ред е индексът imu_ts, третият ред е unix времето при този индекс, а вторият ред е индексът на най-близката стойност на vicon_ts над клеймото за време в същата колона.

Ето моят код досега и той работи, но е наистина бавен. Не съм сигурен как да го векторизирам.

function tmap = sync_times(imu_ts, vicon_ts)

tstart = max(vicon_ts(1), imu_ts(1));
tstop = min(vicon_ts(end), imu_ts(end));

%trim imu data to 
tmap(1,:) = find(imu_ts >= tstart & imu_ts <= tstop);
tmap(3,:) = imu_ts(tmap(1,:));%Use imu_ts as ground truth

%Find nearest indecies in vicon data and map
vic_t = 1;
for i = 1:size(tmap,2)
    %
    while(vicon_ts(vic_t) < tmap(3,i))
        vic_t = vic_t + 1;
    end
    tmap(2,i) = vic_t;
end

Времевите клейма вече са сортирани във възходящ ред, така че това по същество е O(n) операция, но тъй като е зациклена, тя работи бавно. Някакви векторизирани начини да направите същото?

Редактиране Изглежда, че работи по-бързо, отколкото очаквах или първоначално измерено, така че това вече не е критичен проблем. Но ще ми е интересно да видя дали има някакви добри решения на този проблем.


person CodeFusionMobile    schedule 05.02.2013    source източник
comment
Отговорих на подобен въпрос вчера, без да видя този вероятно свързан . Вярвам, че решението там е приложимо и тук, въпреки че изрязването и създаването на 3xd матрица все още трябва да се направят след това.   -  person arne.b    schedule 19.02.2013


Отговори (3)


Разгледайте knnsearch в MATLAB. Използвайте градско разстояние и също така поставете допълнително ограничение, че точката с данни в vicon_ts трябва да бъде по-малка от съседната в imu_ts. Ако не е, вземете следващия индекс. Това е необходимо, защото cityblock отнема абсолютно разстояние. Друг вариант (и предпочитан) е да напишете своя персонализирана функция за разстояние.

person Autonomous    schedule 05.02.2013

Вярвам, че настоящият ви метод е стабилен и не бих се опитвал да векторизирам повече. Векторизацията всъщност може да бъде вредна, когато се опитвате да оптимизирате някои вътрешни цикли, особено когато знаете повече за контекста на вашите данни (напр. те са сортирани), отколкото могат да знаят инженерите на Mathworks.

Нещата, които обикновено търся, когато трябва да оптимизирам част от код като това, са:

  1. Всички масиви са предварително разпределени (това е най-големият двигател на производителността)
  2. Бързите вътрешни цикли използват прост код (Matlab прави доста ефективен JIT на основни команди, но трябва да интерпретира други.)
  3. Възползвайте се от всякакви специални функции за данни, които имате, напр. използвайте подходящи алгоритми за сортиране и условия за ранно излизане от някои цикли.

Ти вече правиш всичко това. Препоръчвам без промяна.

person Pursuit    schedule 05.02.2013

Добро начало може да е да се отървете от while, опитайте нещо като:

for i = 1:size(tmap,2)
    C = max(0,tmap(3,:)-vicon_ts(i));
    tmap(2,i) = find(C==min(C));
end
person Smash    schedule 05.02.2013
comment
Find всъщност би било по-неефективно, защото не предполага сортирани данни. Тъй като данните vic_t са сортирани, общата сложност вече е O(n), така че добавянето на find и max го прави O(n^2) - person CodeFusionMobile; 07.02.2013