我正在尝试创建一个函数,每次调用函数时都会存储一个非常大的变量。我有一个函数myfun(x,y)
,其中y
非常大,因此执行起来很慢,因为MATLAB是按值传递的。但是,我只在程序执行期间传递变量y
一次,创建一个闭包,然后传递给另一个函数重复调用:
Y = create_big_matrix();
newfun = @(x) myfun(x,Y);
some_other_fun(newfun); % This calls newfun several times
我假设每次调用newfun
时,都会将Y
的存储值复制到myfun
。这看起来非常低效。有没有更好的方法来实现newfun
,以便Y
只在创建newfun
时(也可能在传递给some_other_fun
时)复制一次?
答案 0 :(得分:1)
MATLAB has copy-on-write mechanisms会在Y
被调用时阻止myfun(x,Y)
的副本,除非它修改输入。在这种情况下,我认为您不必担心性能问题,但我必须查看myfun
的代码并运行测试以进行验证。
引用this post on a MathWorks blog:
有些用户认为,因为MATLAB的行为就好像数据是按值传递的(而不是通过引用传递),所以MATLAB在调用函数时总是复制输入。这不一定是真的。
本文接着描述了MATLAB识别函数修改变量的能力有限,并尽可能避免复制。另请参阅this SO answer,在写时复制as described in an old newsreader post期间总结“幕后”操作。
要调查是否正在进行复制,请使用format debug
检查调用函数中pr
的数据指针地址Y
,并再次检查myfun
内的数据指针地址{{1}}。如果是相同的,则不会发生任何副本。设置断点以逐步执行并检查此指针。
答案 1 :(得分:0)
由于Y
不是函数句柄的参数,因此它只传递给函数句柄一次,即在执行时 - 包括可能存在的所有花哨的写时复制优化。
所以function_handle在定义时就得到了自己的Y版本。
执行期间,function_handle Y
根本没有传递给function_handle。
您可以通过一个简单的示例来形象化:
>> r = rand();
% at this point the function_handle gets lazy copy of r, stored in its own workspace
>> f = @() r;
>> r
r =
0.6423
% what happens to the original r, doesn't matter to the function-handle:
>> clear r
>> f()
ans =
0.6423
只有在原始Y被修改/删除的情况下才能进行实际复制(在删除时真正复制的可能是另一个问题)。
您可以使用Y
检查functions
是否真的被复制到function_handle工作区,上面的示例(r
只有不同的值):
r =
Structure address = c601538
m = 1
n = 1
pr = 4c834a60
pi = 0
0.4464
>> fcn = functions(f);
>> fcn.workspace{1}.r
ans =
Structure address = c6010c0
m = 1
n = 1
pr = 4c834a60
pi = 0
0.4464
你可以看到,正如chappjc的回答中所讨论的那样,这个参数目前只是懒得复制 - 所以没有创建完整的副本。