Matlab的传值调用的效率问题
本文结论:不要过度担心Matlab的传值调用的效率问题。
刚学Matlab的时候便被告诉Matlab的函数的参数都是通过传值调用(call by value),它的特点是在函数内部对于参数的修改不会影响外面的值。
传值调用参数时,函数内部复制了参数的一份副本。在大多数情况下,这种复制操作的消耗很小,但如果参数对象很大的话(比如为一个1000×1000的矩阵),这样的操作会大大降低函数运行的效率,增加函数调用占用的内存(复制一份对象需要增加使用80M内存)。
幸运的是,Matlab对此进行了优化,如果该参数在函数内部没有被修改,那么在实现时,它实质上用的是传引用调用(call by reference)。
http://www.mathworks.com/support/solutions/en/data/1-15SO4/index.html?solution=1-15SO4
For MATLAB built-in data types, MATLAB always passes arguments 'by value' in the sense that any changes made to input arguments within a function are not visible to the respective variables in the caller workspace.
However, since passing huge chunks of data 'by value' is inefficient, MATLAB internally optimizes for some cases and passes by reference and only creates local copies if modifications are being made to these arguments.
可测试下面的test函数:
function a = test(m, t) if t > 0 if t == 0 m(1, t) = t; end m = subtest(m); a = test(m, t-1) + 1; else a = 1; end function a = subtest(m) a = m;
比如测试 test(rand(1000), 200)。如果函数是使用传值调用,那么它早就奔溃了(因为在200次递归中共需要80M×200=16G内存)。但实际测试中,程序能在1秒钟内给出结果,内存占用也很少。事实上,在程序实际运行的过程中使用的是传引用调用的方式。
更进一步地说,Matlab在程序运行过程中而不是编译的时候(或者刚进入函数的时候)确定用哪种方式调用参数。所以即使发生了赋值操作,只要赋值不修改变量的值(比如a=a这样的赋值),Matlab不会生成副本。只有在变量的值被实质修改时,程序才会生成一个临时副本。
Q.E.D., ©zhiqiang, 2010.09.21。请参考右边的相关文章列表。
刚好我前两天在做这方面的问题。
确实如你所说。
但我还有一个问题,如果参数所占内存很大,而且实质修改了参数的内容呢?
如何才能提高效率?
参数是用结构体形式写成的。
我尝试着将参数搞成global变量,但没有发现性能有明显提升。
几乎无变化。
Global的变量与call by reference的效率应该差不多,你的程序瓶颈估计不在你说的这个地方上。你可以用Matlab带的profiler去查看具体是哪段代码和函数消耗时间过长。
我用了profile,也确实找到了一些问题。但程序中参数传递所带来的代价,到底是算在主函数还是子函数里呢?
你这个问题我以前没考虑过,刚看了下matlab的帮助,感觉应该算在主函数的self time和total time里面。
一般来说,单纯的参数复制带来的时间损耗不太大,毕竟内存上的复制操作很快,它更多体现在内存占用上,如果把变量挤到虚拟内存上也会影响程序速度。
如果你觉得还是程序参数的问题,你可以考虑handle class,它是传引用的。
谢谢了