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

标签 performance matlab function variables global

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

考虑一个循环 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

更新三:

非常感谢@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 后,您可以使用 constants.a1 之类的表达式引用 MAT 文件中的每个常量(constants 因为这是分配给输出的变量的名称loada1 因为这是存储在 example_constants.mat 中的变量的名称。它使用的另一个功能是匿名函数,用于将常量结构的值捕获到 lambda 中,并将其作为每次迭代的第二个输入 (c) 传递给 myfun。

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

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

关于performance - 将大量常量和工作区变量传递给 fsolve 目标函数的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27218341/

相关文章:

ios - 延迟更改 UIImageView.image

function - Haskell 中 lambda 函数的解释

language-agnostic - 有什么好的代码优化方法?

matlab - MATLAB pos 函数的 Haskell/hmatrix 等价物是什么?

Bash 从文件中读取并存储到 MATLAB 中的变量

web-services - 有没有简单的方法来提供基于 Matlab 的 Web 应用程序或 Web 服务?

java - 如何创建一个接受可变数量参数的 Java 方法?

mysql - 大型结果集的数据传输缓慢

c++ - 从派生指针调用虚函数而不支付 vtable 价格

c# - 关于 C# 中 LINQ2Sql 性能的问题