Каков наилучший способ передать множество констант и переменных рабочей области в целевую функцию fsolve?
Для вызова глобальных вызовов требуется смешное количество времени, по сравнению с тем, чтобы вообще не использовать их:
Рассмотрим цикл с 1000 итерациями, выполняющий некоторые вычисления с этими переменными: 0,6 с без глобальных переменных (~1000 переменных), 2,2 с одна определенная глобальная переменная (и другие переменные), 6 с ~ 1000 глобальных переменных (и другие переменные)). Итак, вы видите, что ОПРЕДЕЛЕНИЕ уже одного глобального является шагом, который замедляет итерации в функции, которая значительно использует глобальные переменные, в отличие от того, чтобы не использовать их в первую очередь.
Моя текущая задача - функция fsolve, которая вызывает другую функцию и, по-видимому, требует глобальных переменных. И это большая проблема для меня. Я читал, что вы можете передавать переменные в функцию по-разному, например, используя struct, но эта структура должна была бы быть "распакована" внутри моих итераций, снова замедляя итерации.
Теперь мой вопрос: я не хочу использовать глобалы. Как я могу обойти их в fsolve? Моя идея состоит в том, чтобы загрузить их перед входом в цикл. Пожалуйста, скажите мне, что я могу кое-что сделать здесь.
Спасибо за чтение, пожалуйста, помогите!
ОБНОВЛЕНИЕ I:
% load workspacevars.mat % I'm loading some variables that are going to be used.
one_of_the_variables_that_is_imported = 1;
for loop=1:1000
x(loop,:)=linspace(rand(),1,13); % x is going to change all the time, so I simulate this here
x1=x(loop,1); %
x2=x(loop,2); %
x13=x(loop,13); % shortened so you get the general idea.
result_1 = x1 * one_of_the_variables_that_is_imported
result_2 = x2 * one_of_the_variables_that_is_imported
result_13 = x13 * one_of_the_variables_that_is_imported
end
Итак, еще раз, я хочу использовать ни глобальные переменные, ни загружать рабочее пространство для передачи переменных, как это сработает?
ОБНОВЛЕНИЕ II:
По запросу, это очень, очень близкий пример моей реальной проблемы (пожалуйста, не пугайтесь длины или отображения, код работает, но просто не слишком эффективен). Опять же, пожалуйста, обратите внимание на основную проблему: у меня ~ 1000 констант, которые мне нужно вызывать из файла рабочей области.m или с глобальными переменными, и я не хочу этого делать.
** Незначительные изменения: я считаю, что pastebin более полезен для этой цели: http://pastebin.com/6e1K90fR
ОБНОВЛЕНИЕ III:
большое спасибо @SCFrench!
Я думаю, что я сам понял, насколько ужасно длинны глобалы по сравнению со структурами! Позвольте мне поделиться с вами этой забавной историей:
Работа над сценарием функции заняла ужасно много времени, я не мог понять почему (у нее было какое-то странное отставание!). Пока я не начал редактировать переменные, чтобы они стали структурой - я удалил все определения глобалов и пуф! все светло-синее исчезло и у меня больше нет лагов при редактировании кода!!! Я не могу в это поверить!
Так что теперь я планирую Ctrl+H для каждой отдельной переменной и заменить ее на c.Var. Его около 1000 вар, поэтому я лучше спросить в последний раз перед тем, как начать эту утомительную задачу. Это будет работать потом, я надеюсь. Ваш пример был очень хорош, и чем чаще я его читаю, тем больше получаю. Не могли бы вы в последний раз объяснить, как константы переменных передаются в лямбду и передаются в myfun? Боюсь, я не знаю термин "лямбда" в этом контексте и хотел бы вас лучше понять. Я не могу комментировать ваш комментарий, так что извините за это длинное обновление и большое спасибо заранее!
ОБНОВЛЕНИЕ IV:
Код без глобалов работает ЧЕРНУТ ХОРОШО!!!!!! Большое спасибо всем, это фантастика. Я сократил общее время, затрачиваемое на смешные 20 секунд на итерацию, до менее чем одной секунды. что увеличение эффективности на 95%!!!
Несмотря на то, что я прыгаю от радости, есть одна вещь, которую нужно скорректировать: один из моих результатов в fsolve успешно повторяется, это нормально. но я включил дальнейшее вычисление в f2 (функция, которая должна быть решена), которую не нужно решать, но я все еще хочу выводить ее в моем f1, который вызывает fsolve. Теперь мой код читает
[x,fval,exitflag,output,jacobian] = fsolve(@(x) f2(x, c), x0, параметры);
хотя я бы лучше
[x, y, fval, exitflag, output, jacobian] = fsolve (@ (x) f2 (x, c), x0, параметры);
но я получаю слишком много выходных параметров как ошибку, когда я пытаюсь это сделать. Поэтому мне пришлось вернуться к отчаянным мерам и снова вызвать global y, чтобы обе функции знали y. Как еще вы могли бы сделать это, так как теперь я знаю, насколько ужасны глобалы?
1 ответ
Вот упрощенный пример того, как я мог бы решить эту проблему:
function y = example
% a1 = -2; a2 = -1; save('example_constants.mat')
constants = load('example_constants.mat');
y = fsolve(@(x) myfun(x, constants), [-5;-5]);
end
function F = myfun(x, c)
F = [ 2 * x(1) - x(2) - exp(c.a1 * x(1))
-x(1) + 2 * x(2) - exp(c.a2 * x(2))];
end
Это использует две функции MATLAB. Во-первых, если вы запрашиваете вывод из load
, он сохраняет все загруженные переменные как поля структуры и возвращает структуру в качестве ее вывода. После вызова load вы ссылаетесь на каждую константу в MAT-файле, используя выражения типа constants.a1
(constants
потому что это имя переменной, присвоенной выводу load
, а также a1
потому что это имя переменной, которая была сохранена в example_constants.mat). Другая функция, которую он использует, - это анонимные функции, которые записывают значение структуры констант в лямбду и передают его myfun в качестве второго ввода (c
) на каждой итерации.
(В вашем вопросе упоминаются накладные расходы на "распаковку" структурных массивов. Такие затраты на распаковку, если они даже заметны, будут намного ниже, чем стоимость глобальных переменных или оператора загрузки, выполняемого каждый раз, когда вызывается целевая функция.)
Это предполагает, что вам не нужна ваша целевая функция для обновления значений констант (в этом случае они на самом деле не являются константами, и ваш вариант "load w.mat" не будет работать). Если вам это нужно, вы должны посмотреть на похожую технику, используя вложенные функции. Оба эти метода обсуждаются здесь далее.