Как писать векторизованные функции в MATLAB

Я только изучаю 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 раз быстрее, чем вложенные циклы .

Мне действительно трудно понять, как лидирующий в отрасли язык может иметь такую ​​огромную разницу в производительности в зависимости от стиля программирования, но я вижу моменты, упомянутые в ответах ниже.

6
задан Community 23 May 2017 в 12:15
поделиться