与根本不使用全局变量相比,调用全局变量需要花费大量时间来加载:
考虑一个循环 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
因为这是分配给输出的变量的名称load
和 a1
因为这是存储在 example_constants.mat 中的变量的名称。它使用的另一个功能是匿名函数,用于将常量结构的值捕获到 lambda 中,并将其作为每次迭代的第二个输入 (c
) 传递给 myfun。
(您的问题提到了“解包”结构数组的开销。这种解包成本,如果它们甚至是明显的,将远远低于每次目标函数执行时全局变量或加载语句的成本调用。)
这是假设您不需要目标函数来更新常量的值(在这种情况下,它们不是真正的常量,并且您的“load w.mat”变体将不起作用)。如果您确实需要,您应该考虑使用嵌套函数的类似技术。这两种技术都将进一步讨论here .
关于performance - 将大量常量和工作区变量传递给 fsolve 目标函数的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27218341/