Ускорение вложенного цикла for

Я работал над ускорением следующей функции, но безрезультатно:

function beta = beta_c(k,c,gamma)
beta = zeros(size(k));
E = @(x) (1.453*x.^4)./((1 + x.^2).^(17/6));
for ii = 1:size(k,1)
    for jj = 1:size(k,2)
        E_int = integral(E,k(ii,jj),10000);
        beta(ii,jj) = c*gamma/(k(ii,jj)*sqrt(E_int));
    end
end
end

До сих пор я решил это так:

function beta = beta_calc(k,c,gamma)
k_1d = reshape(k,[1,numel(k)]);
E_1d =@(k) 1.453.*k.^4./((1 + k.^2).^(17/6));
E_int = zeros(1,numel(k_1d));
parfor ii = 1:numel(k_1d)
E_int(ii) = quad(E_1d,k_1d(ii),10000);
end
beta_1d = c*gamma./(k_1d.*sqrt(E_int));
beta = reshape(beta_1d,[size(k,1),size(k,2)]);
end

Мне кажется, это не особо улучшило выступления. Что Вы думаете об этом?

Не могли бы вы пролить свет?

Я благодарю вас заранее.

ИЗМЕНИТЬ

Я собираюсь представить некоторые теоретические основы, связанные с моим вопросом. Как правило, бета рассчитывается следующим образом.

введите здесь описание изображения

Следовательно, в сокращенном случае одномерного массива k E_int можно рассчитать как

E = 1.453.*k.^4./((1 + k.^2).^(17/6));
E_int = 1.5 - cumtrapz(k,E);

или, альтернативно, как

E_int(1) = 1.5;
for jj = 2:numel(k)
E =@(k) 1.453.*k.^4./((1 + k.^2).^(17/6));
E_int(jj) = E_int(jj - 1) - integral(E,k(jj-1),k(jj));
end

Тем не менее, k в настоящее время является матрицей k(size1,size2).


person fpe    schedule 20.01.2013    source источник
comment
Лучше всего было бы скомпилировать функцию как мекс - это будет намного быстрее.   -  person Floris    schedule 20.01.2013
comment
@fpe Не по теме: в текущих версиях MATLAB я никогда не видел, чтобы arrayfun работал быстрее, чем цикл for.   -  person Eitan T    schedule 20.01.2013
comment
Я не знаком с интегралом, но разве он не может принимать две матрицы в ?   -  person Pavan Yalamanchili    schedule 20.01.2013
comment
@EitanT: я бы хотел оптимизировать производительность вышеуказанной функции. Может ли векторизация быть ответом?   -  person fpe    schedule 20.01.2013
comment
@Pavan: я думаю, что интегралу нужны скаляры в качестве пределов интегрирования.   -  person fpe    schedule 20.01.2013


Ответы (2)


Вот еще один подход, распараллелить, потому что легко использовать spmd или parfor. Вместо integral рассмотрите quad, см. примеры по этой ссылке. ..

person bla    schedule 21.01.2013
comment
Я только что отредактировал свой вопрос, введя parfor в выражение beta_calc. Время выполнения тематического исследования magic(100) вдвое меньше, чем раньше. Неплохой результат, но не знаю, достаточно ли - person fpe; 21.01.2013
comment
Ваш намек кажется сейчас самым разумным решением. Спасибо - person fpe; 21.01.2013

Мне нравится этот вопрос.

Проблема: функция integral принимает в качестве ограничений интегрирования только скаляры. Следовательно, трудно векторизовать вычисление E_int.

Подсказка: похоже, много избыточности в интеграции одной и той же функции снова и снова от k(ii,jj) до бесконечности...

Предлагаемое решение. Как насчет сортировки значений k от наименьшего к наибольшему и интегрирования E_sort_int(si) = integral( E, sortedK(si), sortedK(si+1) ); с sortedK( numel(k) + 1 ) = 10000;. Затем полное значение E_int = cumsum( E_sort_int ); (вам нужно только «отменить» сортировку и изменить ее обратно до размера k).

person Shai    schedule 20.01.2013
comment
на самом деле E_int в качестве интегральных пределов должен принимать |k| и Инф; кстати, как вы утверждаете, я могу вычислить E_int альтернативным способом, который я опубликую как редактирование основного вопроса (обратите внимание, что я представлю его в случае, если k является одномерным массивом) - person fpe; 20.01.2013
comment
Я начал думать, что, возможно, проще смешать функцию C с учетом той, которую я сейчас вызываю в Matlab; по крайней мере относительно integral - person fpe; 21.01.2013