векторизация циклов в Matlab - проблемы с производительностью - PullRequest
1 голос
/ 23 мая 2010

Этот вопрос связан с этими двумя:
Введение в векторизацию в MATLAB - есть ли хорошие уроки?
Фильтр, который использует элементы из двух массивов одновременно

Основываясь на прочитанных мною уроках, я пытался векторизовать какую-то процедуру, которая занимает действительно много времени.

Я переписал это:

function B = bfltGray(A,w,sigma_r)
dim = size(A);
B = zeros(dim);
for i = 1:dim(1)
    for j = 1:dim(2)

        % Extract local region.
        iMin = max(i-w,1);
        iMax = min(i+w,dim(1));
        jMin = max(j-w,1);
        jMax = min(j+w,dim(2));
        I = A(iMin:iMax,jMin:jMax);

        % Compute Gaussian intensity weights.
        F = exp(-0.5*(abs(I-A(i,j))/sigma_r).^2);
        B(i,j) = sum(F(:).*I(:))/sum(F(:));

    end
end

в это:

function B = rngVect(A, w, sigma)
W = 2*w+1;
I = padarray(A, [w,w],'symmetric');
I = im2col(I, [W,W]);
H = exp(-0.5*(abs(I-repmat(A(:)', size(I,1),1))/sigma).^2);
B = reshape(sum(H.*I,1)./sum(H,1), size(A, 1), []);

Где
A - матрица 512x512
wравно половине размера окна, обычно равно 5
sigma - параметр в диапазоне [0 1] (обычно один из: 0,1, 0,2 или 0,3)
Таким образом, матрица I будет иметь 512x512x121 = 31719424elements

Но эта версия кажется такой же медленной, как и первая, но, кроме того, она использует много памяти и иногда вызывает проблемы с памятью.

Полагаю, я сделал что-то не так.Вероятно, какая-то логическая ошибка в отношении векторизации.Ну, на самом деле, я не удивлен - этот метод создает действительно большие матрицы и, вероятно, вычисления пропорционально длиннее.

Я также пытался написать его, используя nlfilter (аналогично второму решению, данномуДжонас ), но это кажется трудным, поскольку я использую Matlab 6.5 (R13) (нет доступных сложных функциональных дескрипторов).

Итак, еще раз, я прошу не о готовом решении, а о некоторых идеях, которые помогут мне решить это в разумные сроки.Может быть, вы укажете мне, что я сделал не так.

Редактировать:
Как предположил Михаил, результаты профилирования следующие:
65% времени было потрачено в строке H= exp(...)
25%время использовалось im2col

1 Ответ

1 голос
/ 23 мая 2010

Насколько велики я и Н (т. Е. numel(I)*8 байт)? Если вы начнете пейджинг, то производительность вашего второго решения будет сильно ухудшена.

Чтобы проверить, действительно ли у вас возникли проблемы из-за слишком больших массивов, вы можете попробовать измерить скорость вычислений, используя tic и toc для массивов A увеличивающегося размера. Если время выполнения увеличивается быстрее, чем на квадрат размера A, или если время выполнения увеличивается до некоторого размера A, вы можете попытаться разделить заполненный I на несколько подмассивов и выполнить подобные расчеты.

В противном случае, я не вижу очевидных мест, где вы могли бы терять много времени. Ну, может быть, вы могли бы пропустить изменение формы, заменив B на A в своей функции (также экономит немного памяти) и написав A(:) = sum(H.*I,1)./sum(H,1);

Возможно, вы также захотите перейти на более новую версию Matlab - они усердно работали над повышением производительности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...