问题描述
调用全局变量需要花费大量的时间来进行加载,而不是完全不使用它们:考虑一个1000次迭代循环,用这些变量进行一些计算:0 ,6秒没有全局变量(〜1000个变量),2,2秒一个定义了全局变量(和其他变量),6秒〜1000个全局变量(和其他变量)。所以,你已经看到了DEFINING已经有一个全局是一个放慢使用全局变量的函数迭代的步骤,而不是首先使用全局变量。
我目前面临的挑战是fsolve函数,它调用另一个函数并且看起来需要全局变量。这对我来说是个大问题。我读过,你可以通过不同的方式向函数传递变量,比如通过使用struct,但是这个结构必须在我的迭代中解压,再次减慢迭代次数。
现在我的问题是:我不想使用全局变量。我怎样才能在fsolve中规避他们?我的想法是在进入循环之前加载它们。请告诉我,我可以在这里做些什么。
感谢您的阅读,请帮助!
更新I:
%load workspacevars.mat%我加载了一些将要用过的。
one_of_the_variables_that_is_imported = 1;
for循环= 1:1000
x(循环,:)= linspace(rand(),1,13); %x会一直改变,所以我在这里模拟
x1 = x(loop,1); %
x2 = x(loop,2); %
x13 = x(loop,13); %缩短了,所以你得到了一般的想法。
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对此更有用:
更新III:
非常感谢@SCFrench!
我想我自己弄明白了全局变量与结构体相比是多么的可怕!让我与你分享这个有趣的故事:
在函数脚本中工作花了很长时间,我无法弄清楚为什么(它有一些奇怪的滞后!)。直到我开始编辑变量变成结构体 - 我删除了所有的全局变量定义和poof!一切亮蓝消失,我没有更多的时间在编辑代码!!!我无法相信这一点!
所以我现在的计划是按Ctrl + H将每个变量都替换为c.Var。它的大约1000 Var,所以我最好再问一次,然后才开始这个乏味的任务。这将继续工作,我希望。你的例子非常好,我越读得越多。你可能最后一次解释一下变量常量是如何传递给lambda并传递给myfun的?我担心在这种情况下我不知道术语拉姆达,并希望更好地理解你。我无法对您的评论发表评论,所以对于此次冗长的更新感到抱歉,并提前致谢!
更新IV:
无全局代码 DARN WELL !!!!!!非常感谢大家,这太棒了。我将每次迭代荒谬的20秒所花费的总时间缩短到不到1秒。效率提高95%!!!即使我喜欢跳跃,也有一件事需要调整:我的一个结果是fsolve是迭代成功,那没关系。但是我在f2中包含了一个进一步的计算(函数是fsolved),它不需要被解析,但我仍然希望在我的f1中调用fsolve的输出。现在我的代码读取:
[x,fval,exitflag,output,jacobian] = fsolve(@(x)f2(x,c),x0,options);
尽管Id有相当的功能,输出,jacobian] = fsolve(@(x)f2(x,c),x0,options);
但是当我尝试时,输出参数太多那。所以我不得不重新采取绝望的措施,并再次呼吁全球y,所以这两个函数都知道y。那么你会怎么做,因为我现在知道全局有多可怕了?
关于解决这个问题:
函数y =示例
%a1 = -2; a2 = -1; save('example_constants.mat')
constants = load('example_constants.mat');
y = fsolve(@(x)myfun(x,constants),[-5; -5]);
函数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
(常量
>因为这是指定输出load
和a1
的变量的名称,因为这是已存储在example_constants.mat中的变量)。这个使用的另一个特性是匿名函数,用于将常量结构的值捕获到lambda中,并在每次迭代中将其作为第二个输入(c
)传递给myfun。 / b>
(你的问题提到了拆包结构数组的开销,如果这些拆包成本明显的话,将会远远低于全局变量的成本或每次调用目标函数时执行的加载语句)。
这假设您不需要目标函数来更新常量的值(其中情况下,它们并不是真正的常量,而你的load w.mat变体将不起作用)。如果你确实需要这个,你应该看看使用嵌套函数的类似技巧。这两种技术将在进一步讨论。
Calling globals requires a ridiculous amount of time to load compared to not using them at all:
Consider a loop with 1000 iterations doing some calculation with those variables: 0,6 sec no globals (~1000 variables), 2,2 sec one defined global variable (and the other variables), 6 sec ~1000 globals (and the other variables). So you see DEFINING already one global is the step which slows down iterations in a function that uses globals considerably, in contrast to not using them in the first place.
My current challenge is the fsolve function which calls another function and seemingly requires global variables. And this is a big problem for me. I read you can pass variables differently to the function, for instance by using struct but this struct would have to be "unpacked" inside my iterations, slowing down iterations again.
Now my question: I dont want to use globals. How can I circumvent them in fsolve? My idea is to load them before entering the loop. Please tell me there is something I can do here.
Thank you for reading, please help!
UPDATE 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
So again, I wish to use nor globals nor load workspace to pass the variables, how would that work out?
UPDATE II:
Upon request, here is a very, very close example to my actual problem (please dont be intimidated by the length or display, the code works but is just not overly efficient). Again, please focus on the main problem that I have ~1000 constants that I have to call from a .m workspace file or with globals and dont wish to do that.
**Minor modification: I find pastebin more useful for this purpose: http://pastebin.com/6e1K90fR
UPDATE III:
big thanks to @SCFrench!
I think I just figured it out myself how horribly long globals take compared to structs! Let me share this funny story with you:
Working in the script of the function took terribly long, I couldnt figure out why (it had some strange lag!). Until I started editing the variables to become structure - I deleted all globals definitions and poof! everything light-blue disappeared and I have no more lags in editing the code!!! I cant believe this!
So my plan is now to ctrl+H every single variable I have and replace it with c.Var. Its around 1000 Var so I better ask one last time before starting this tedious task. It will work afterwards I hope. Your example was very good, and the more often I read it the more I get. Could you maybe explain one last time how the variable constants is passed into a lambda and passed to myfun? I fear I dont know the term lambda in this context and would like to understand you better. I cant comment on your comment so sorry for this lengthy update and many thanks in advance!
UPDATE IV:
The code without globals works DARN WELL !!!!!! many thanks to everybody, this is fantastic. I reduced the total time it took from ridiculous 20 sec per iteration to less than one sec. that a 95% increase in efficiency!!!
Even though I am jumping of joy, there is one thing that needs to be adjusted: one of my results in fsolve is iterated successfully, thats ok. but I included a further calculation in f2 (the function to be fsolved) that doesnt need to be fsolved but I still want the output of it in my f1 that calls fsolve. Now my code reads
[x,fval,exitflag,output,jacobian] = fsolve(@(x) f2(x, c), x0, options);
although Id rather have
[x,y,fval,exitflag,output,jacobian] = fsolve(@(x) f2(x, c), x0, options);
but I get too many output parameters as error when I attempt that. So I had to reort to desperate measures and call global y again so both functions know y. How else would you do that since I now know how horrible globals are?
解决方案Here is a simplified example of how I would go about solving this:
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
This uses two features of MATLAB. First, if you request an output from
load
, it stores all the loaded variables as fields of a structure and returns the structure as its output. After the call to load, you refer to each constant in the MAT-file by using expressions likeconstants.a1
(constants
because that is the name of the variable assigned the output ofload
, anda1
because that is the name of the variable that had been stored in example_constants.mat). The other feature this uses are anonymous functions, to capture the value of the constants structure into a lambda and pass it to myfun as the second input (c
) on each iteration.(Your question mentions the overhead of "unpacking" structure arrays. Such unpacking costs, if they are even noticeable, will be far, far less than the cost of either global variables or a load statement executed each time the objective function is called.)
This is assuming you don't need your objective function to update the values of the constants (in which case, they aren't really constants, and your "load w.mat" variant wouldn't work). If you do need that, you should look at a similar technique using nested functions. Both of these techniques are discussed further here.
这篇关于将大量常量和工作空间变量传递给fsolve目标函数的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!