Matlab中变量拷贝的原理?
-- copy-on-write和mex参数传递机制解析
本质概括:写入时复制(英语:Copy-on-write,简称COW)是一种计算机程序设计领域的优化策略。其核心思想是,如果有多个调用者(callers)同时要求相同资源(如内存或磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本(private copy)给该调用者,而其他调用者所见到的最初的资源仍然保持不变。这过程对其他的调用者都是透明的(transparently)。此作法主要的优点是如果调用者没有修改该资源,就不会有副本(private copy)被创建,因此多个调用者只是读取操作时可以共享同一份资源。
Matlab真是让人又爱又恨,诸多强大的工具包以及矩阵(向量)运算的便捷与高效让人欲罢不能(那种一行代码抵C++等效的10+行循环代码的感觉真是爽到不行)。不过最近做实验用Matlab让我吃了不少苦头,主要就是因为对它的copy-on-write机制以及mex文件的参数传递机制不了解。另外感觉这方面内容虽然一般不怎么涉及,但是对于理解Matlab并且充分发挥出它对矩阵运算的高效性而又不陷入无谓且难以察觉的臭虫堆(切身体会啊!)十分重要,又加之中文的关于这方面的材料十分稀缺(我几乎就没见到……),所以在这里稍作总结,便于今后自己查阅也方便有需要的人。
1. 先解释下2个关键词:
a. copy-on-write:我们晓得变量在内存里存储都有一个地址,而有的时候我们需要把一个变量A的值拷贝一份产生一个新的变量B。所谓copy-on-write说的就是制造这么一个假象,让你觉得好像已经拷贝过了,但是其实只是让那个新变量也指向原来的内存地址(因为这样对于仅仅读取变量值而言是等效的),只有当那个值必须发生改变的时候(或者说被写入的时候)才赶紧把原先的内容拷贝出来,存到一个新的地方(如果改写的是A,就存给B;如果改写的是B,就存给A)。
说白了就是偷懒+说谎——直到要被戳穿了不得已为止。不过这样做当然是有好处的,因为拷贝内存是有开销的(即使是线性开销),因此能省则省呗。特别对于Matlab这样的动不动开个庞大矩阵做运算的语言来讲,copy-on-write对于性能提升至关重要。
b. mex传参:mex是"Matlab Executable"的缩写,是个非常强大的机制。有了它以后,Matlab难以体现其优势的代码(比如多重循环)就可以转而用C(C++貌似也可以)或者FORTRAN来实现,通过预先编译产生动态链接库文件(就是dll)为Matlab进程调用,并且调用接口与直接调用Matlab函数几乎完全一样(好吧,只是"几乎"而已,不然我就不会碰到那些个bug了……)。
具体的mex介绍不是本文重点,就此略过。这里所谓的"mex传参"就是指在Matlab里调用mex函数的时候,不同的传参方式对于mex函数实际运行的影响。
2. Matlab的变量类型有蛮多种,为了后面方便讨论,我们这里采用以下划分标准:
a. Scalar类型:就是单个的数值(实数或者虚数都可以,总之是个复数吧),也可以理解成1*1的矩阵;