Есть ли способ выполнить функцию встраивания в MATLAB? - PullRequest
4 голосов
/ 11 марта 2011

Какую языковую функцию или нестандартный хак можно использовать для выполнения встраивания функций в MATLAB?Досадно, что поиск Google для «встроенной функции matlab» показывает, что дизайнеры MATLAB думали, что «встроить» означает «создать анонимную функцию из строки» (... wtf?).

Причина, по которой я спрашиваю, - я пишу сценарий, который должен работать быстро, и я сталкиваюсь с множеством ситуаций, когда было бы неплохо, чтобы вспомогательная функция обрабатывала какое-то простое дополнение или что-то, чтобы избежать случайногоошибки.Однако стоимость вызова функции (измеренная tic/toc) не будет стоить того.Я отказываюсь верить, что в MATLAB не было бы функции встраивания функций, потому что это препятствовало бы декомпозиции!

В худшем случае я мог бы прибегнуть к использованию макросов M4 .


РЕДАКТИРОВАТЬ: В ответ на комментарий Ета, вот ситуация, в которой я хотел бы встроить помощника:

В какой-то момент мне нужно зациклить (да, я знаю) по всем окнам шириной windowWidth в пределахсписок:

lastWindowStartIdx = length(list) - windowWidth + 1;
for windowStartIdx = 1:lastWindowStartIdx
   display(list[windowStartIdx:windowStartIdx+windowWidth-1]); %the window we're looking at
end

Было бы неплохо иметь возможность вычленить эти хитрые, неустранимые и подверженные ошибкам вычисления windowWidth.Например:

lastWindowStartIdx = calcLastWindowStartIdx(length(list), windowWidth);
for windowStartIdx = 1:lastWindowStartIdx
   display(list[windowStartIdx:calcWindowEndIdx(windowStartIdx, windowWidth)]); %the window we're looking at
end

Ответы [ 2 ]

9 голосов
/ 11 марта 2011

Конкретный ответ:

Что касается вашего примера использования, это, честно говоря, кажется мне своего рода микрооптимизацией. Эти операции «плюс один», безусловно, не являются узким местом в вашем коде, препятствующем его быстрому выполнению, поэтому вместо этого вам следует сосредоточиться на ускорении тех частей кода, где выполняется большая часть ваших вычислений.

Если вы хотите внести это изменение только по эстетическим (написано с первого раза!) Причинам или потому, что вам просто не нравится отслеживать дополнительные, то создайте функцию для обработки, как в вашем На мой взгляд, пример - плохой выбор, потому что он делает код намного сложнее для чтения и понимания. Я бы предложил просто создать новую переменную примерно так:

windowOffset = windowWidth - 1;
lastWindowStartIdx = length(list) - windowOffset;
for windowStartIdx = 1:lastWindowStartIdx
   display(list[windowStartIdx:windowStartIdx + windowOffset]);
end

Общий ответ:

Относительно вашего более общего вопроса о том, как создать настоящие встроенные функции в MATLAB, как вы можете это сделать в C или C ++, я не верю, что есть какой-либо способ сделать это. Я подумал, что, возможно, анонимная функция может соответствовать всем требованиям, но после некоторых простых сравнений по времени с количеством различных типов функций в MATLAB я обнаружил, что анонимная функция на самом деле медленнее чем хорошая старая функция для простой операции +1.

Вот примеры функций, которые я тестировал:

function parent_function
  add_one_anon = @(A) A+1;         %# An anonymous function
  add_one_inline = inline('A+1');  %# An "inline" function
  function add_one_nest            %# A nested function
    A = A+1;
  end
  %# Did the timing here ...
end
function A = add_one_sub(A)        %# A subfunction
  A = A+1;
end

Я выполнял каждое из этих 100 000 раз, увеличивая скалярное значение, которое начиналось с 1, и вот результаты:

            | Time (sec)
------------+------------       
subfunction |   0.0507
anonymous   |   0.0672
nested      |   0.0932
inline      |  14.7095

Если бы анонимные функции действовали как настоящие встроенные функции, я бы ожидал, что они будут самым быстрым решением.

0 голосов
/ 11 марта 2011

Короче говоря, вы не можете inline, в терминах C ++, функционировать в MATLAB. Вы, вероятно, уже знаете это, но циклы в MATLAB работают медленно, и вам следует заменить их на векторизованные операции.

Если вам нужно ускорить только вызов функции, вам, вероятно, следует предварительно вычислить все ваши индексы как векторизованную операцию, а затем выполнить цикл по результатам.

windows = window_ranges(1, length(list), windowWidth);
for i = 1:size(windows,1),
   display(list[windows(i,1):windows(i,2)]);
end

function [ windows ] = window_ranges ( lower, upper, span )
    count = upper - span;
    windows = zeros(count, 2);
    windows(:,1) = 1:count;
    windows(:,2) = windows(:,1)+span-1;
end
...