Я только изучаю MATLAB, и мне трудно понять коэффициенты производительности циклов по сравнению с векторизованными функциями.
В моем предыдущем вопросе: Вложенные циклы for очень медленные в MATLAB (предварительно выделенные) Я понял, что использование векторизованной функции против 4 вложенных циклов увеличило время выполнения в 7 раз .
В этом примере вместо перебора всех измерений четырехмерного массива и вычисления медианы для каждого вектора было намного проще и быстрее просто вызвать median (stack, n), где n означало рабочее измерение медианной функции.
Но медиана - это просто очень простой пример, и мне просто повезло , что в нем реализован этот параметр измерения .
Мой вопрос: как написать функцию, которая работает так же эффективно, как функция, в которой реализован этот диапазон измерений ?
Например, у вас есть функция my_median_1D
, которая работает только с одномерным вектором и возвращает число.
Как написать функцию my_median_nD
, которая действует как медиана MATLAB, принимая n-мерный массив и параметр «рабочее измерение» ?
Обновление
Я нашел код для вычисления медианы в более высоких измерениях
% In all other cases, use linear indexing to determine exact location
% of medians. Use linear indices to extract medians, then reshape at
% end to appropriate size.
cumSize = cumprod(s);
total = cumSize(end); % Equivalent to NUMEL(x)
numMedians = total / nCompare;
numConseq = cumSize(dim - 1); % Number of consecutive indices
increment = cumSize(dim); % Gap between runs of indices
ixMedians = 1;
y = repmat(x(1),numMedians,1); % Preallocate appropriate type
% Nested FOR loop tracks down medians by their indices.
for seqIndex = 1:increment:total
for consIndex = half*numConseq:(half+1)*numConseq-1
absIndex = seqIndex + consIndex;
y(ixMedians) = x(absIndex);
ixMedians = ixMedians + 1;
end
end
% Average in second value if n is even
if 2*half == nCompare
ixMedians = 1;
for seqIndex = 1:increment:total
for consIndex = (half-1)*numConseq:half*numConseq-1
absIndex = seqIndex + consIndex;
y(ixMedians) = meanof(x(absIndex),y(ixMedians));
ixMedians = ixMedians + 1;
end
end
end
% Check last indices for NaN
ixMedians = 1;
for seqIndex = 1:increment:total
for consIndex = (nCompare-1)*numConseq:nCompare*numConseq-1
absIndex = seqIndex + consIndex;
if isnan(x(absIndex))
y(ixMedians) = NaN;
end
ixMedians = ixMedians + 1;
end
end
. Не могли бы вы объяснить мне, что почему этот код настолько эффективен по сравнению с простыми вложенными циклами ? Он имеет вложенные циклы, как и другая функция.
Я не понимаю , как это могло быть в 7 раз быстрее , а также то , почему это так сложно .
Обновление 2
Я понял, что использование медианы не является хорошим примером, поскольку сама по себе сложная функция требует сортировки массива или других изящных уловок. Вместо этого я повторно провел тесты со средним значением, и результаты стали еще более сумасшедшими: 19 секунд против 0,12 секунды. Это означает, что встроенный способ для суммы в 160 раз быстрее, чем вложенные циклы .
Мне действительно трудно понять, как лидирующий в отрасли язык может иметь такую огромную разницу в производительности в зависимости от стиля программирования, но я вижу моменты, упомянутые в ответах ниже.