将大量常量和工作区变量传递给 fsolve 目标函数的最佳方法是什么?

2024-01-13

与根本不使用全局变量相比,调用全局变量需要花费大量时间来加载:

考虑一个具有 1000 次迭代的循环,对这些变量进行一些计算:0.6 秒没有全局变量(约 1000 个变量),2.2 秒一个定义的全局变量(和其他变量),6 秒约 1000 个全局变量(和其他变量) )。因此,您会发现,与一开始就不使用全局变量相比,定义一个全局变量会减慢大量使用全局变量的函数中的迭代速度。

我当前的挑战是 fsolve 函数,它调用另一个函数并且似乎需要全局变量。这对我来说是一个大问题。我读到您可以将变量以不同的方式传递给函数,例如通过使用结构,但该结构必须在我的迭代中“解压”,从而再次减慢迭代速度。

现在我的问题:我不想使用全局变量。我如何在 fsolve 中规避它们?我的想法是在进入循环之前加载它们。请告诉我这里有什么我可以做的。

感谢您的阅读,请帮忙!

更新一:

   % 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

再说一次,我希望使用全局变量或加载工作空间来传递变量,这会如何解决?

更新二:

根据要求,这是一个与我的实际问题非常非常接近的示例(请不要被长度或显示吓倒,代码可以工作,但效率不太高)。再次,请关注主要问题,即我有大约 1000 个常量,我必须从 .m 工作区文件或全局变量调用这些常量,但我不希望这样做。

**小修改:我发现pastebin对此目的更有用:http://pastebin.com/6e1K90fR http://pastebin.com/6e1K90fR

更新三:

非常感谢@SCFrench!

我想我自己才发现全局变量与结构体相比需要多长时间!给大家分享一个有趣的故事:

在函数脚本中工作花费了非常长的时间,我无法弄清楚为什么(它有一些奇怪的滞后!)。直到我开始编辑变量以使其成为结构 - 我删除了所有全局定义,然后噗!所有浅蓝色的东西都消失了,我在编辑代码时不再有任何滞后!我简直不敢相信!

所以我现在的计划是 ctrl+H 我拥有的每个变量并将其替换为 c.Var。大约是 1000 Var,所以我最好在开始这项繁琐的任务之前问最后一次。我希望之后它会起作用。你的例子非常好,我读得越多,收获就越多。您能否最后解释一下变量常量是如何传递到 lambda 并传递给 myfun 的?我担心我不知道这种情况下的 lambda 一词,并且想更好地理解您。我无法对您的评论发表评论,因此对于这个冗长的更新感到抱歉,并提前非常感谢!

更新四:

没有全局变量的代码可以工作好极了!!!!!!非常感谢大家,这太棒了。我将每次迭代花费的总时间从可笑的 20 秒减少到不到 1 秒。效率提高 95%!

尽管我欣喜若狂,但有一点需要调整:我在 fsolve 中的结果之一迭代成功,没关系。但我在 f2 (要进行 fsolve 的函数)中包含了进一步的计算,不需要进行 fsolve,但我仍然希望在调用 fsolve 的 f1 中输出它。现在我的代码如下

[x,fval,exitflag,输出,雅可比] = fsolve(@(x) f2(x, c), x0, 选项);

虽然我宁愿有

[x,y,fval,exitflag,输出,雅可比] = fsolve(@(x) f2(x, c), x0, 选项);

但是当我尝试这样做时,我得到了太多的输出参数作为错误。所以我不得不采取绝望的措施并再次调用全局 y,以便两个函数都知道 y。既然我现在知道全局变量有多么可怕,你还能怎么做呢?


这是我如何解决这个问题的一个简化示例:

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, and a1因为这是存储在 example_constants.mat 中的变量的名称。它使用的另一个功能是匿名函数,用于将常量结构的值捕获到 lambda 中并将其传递给 myfun 作为第二个输入(c)在每次迭代中。

(你的问题提到了“解包”结构数组的开销。这种解包成本,如果它们甚至是明显的,将远远低于全局变量或每次调用目标函数时执行的加载语句的成本。)

这是假设您不需要目标函数来更新常量的值(在这种情况下,它们不是真正的常量,并且您的“load w.mat”变体将不起作用)。如果您确实需要,您应该考虑使用嵌套函数的类似技术。这两种技术都将进一步讨论here http://www.mathworks.com/help/optim/ug/passing-extra-parameters.html.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将大量常量和工作区变量传递给 fsolve 目标函数的最佳方法是什么? 的相关文章

随机推荐