Matlab 变量在复制并传递到 mex 文件时显示“类似引用”的行为

Posted

技术标签:

【中文标题】Matlab 变量在复制并传递到 mex 文件时显示“类似引用”的行为【英文标题】:Matlab variables show 'reference-like' behavior when copied and passed to a mex file 【发布时间】:2012-01-24 10:03:11 【问题描述】:

我有一个接受变量并更改它的 mex 文件(在 VS2010、Matlab 2010b 中编译)。例如,在 mex 文件中它看起来像:

double *fp = (double *)mxGetPr (prhs[0]);
*fp = someDoubleValue;

为了比较Matlab实现和mex实现,我在调用mex文件之前做了一个变量的拷贝:

var_mex = var;
mymex (var_mex);

令我惊讶的是,var_mexvar 都发生了变化(当然是相同的值),就好像我创建了对 var 的引用而不是它的副本。

这是一个已知问题吗?如何说服 Matlab 复制变量?

编辑

由于我怀疑这个问题是 Matlab 优化其内存管理的结果,我在调用 mex 文件之前对 var 做了一些“什么都不做”计算,即

var=var+1;
var=var-1;

确实可以解决问题。如果有人也遇到它,我仍然很乐意获得有关此的一些信息(或其他建议)。

【问题讨论】:

这似乎是由this page 设计的。也许您可以在传递之前修改 var_mex,例如将其乘以 1。或者在两个离散的步骤中加 1 然后减 1。 是的,这正是我尝试过的(并且有效,请参阅我的编辑)。 您是否阅读了Matlab's memory management 上的 Matlab 文档?它解释了这种行为。 【参考方案1】:

在 MATLAB 中,大多数变量都按值传递一样传递。值得注意的例外是从handle 继承的类的实例是通过引用显式传递的。

有一个blog entry here 对此进行了详细介绍。

所以,当你执行时

var_mex = var;

您最终会得到var_mex 引用与var 相同的数据。

当您在 mex 函数中写入 mxArray 时,您拥有强大的破坏能力,因为您获得了数据的底层地址。如果您修改 prhs 数组的元素,您可能会无意中最终修改共享相同数据的其他变量。所以,不要那样做。事实上,mex doc 明确告诉你不要这样做。

var + 1 技巧起作用的原因是,通过修改数据,您会强制 MATLAB 制作数据的副本。

【讨论】:

“所以不要那样做。事实上,墨西哥文档明确告诉你不要那样做”+1 :) mex 机制不会阻止您更改输入变量是否有特定原因? 嗯,mex 接口确实指定 prhs 指针是 const。 mex 接口可以保证您不会对 prhs 造成可见修改的唯一可行方法是,如果它们在进入 mex 函数的途中被复制 - 这将非常低效。 MATLAB 相信您在使用 mex 文件时穿上您的大男孩 C 裤。 我要澄清一下,Matlab 会进行“惰性”复制。因此,只要变量没有被修改,它的任何副本实际上都是对原始数据的引用。一旦变量被修改,就会产生一个副本。 Matlab 的函数知道什么时候在修改之前复制东西,但你的 mex 文件不知道。【参考方案2】:

Matlab 中的所有变量都是按值传递的。

官方不支持直接对 Matlab mexfunction 中的 rhs 参数进行任何更改。 如果要转换 A = func(A) 形式的 Matlab 函数,则“需要”在 mexfunction 本身内复制传递的数组 A

【讨论】:

在 MATLAB 语言本身中,变量是使用写时复制语义按值传递。这解释了为什么添加加法/减法“修复”事物 - 值被修改,因此必须制作副本。一旦您进入了 MEX 文件的世界 - 您就靠自己了,并且可以在一定程度上颠覆 MATLAB 的标准内存管理。 @Edric:为什么不将评论扩展为答案?

以上是关于Matlab 变量在复制并传递到 mex 文件时显示“类似引用”的行为的主要内容,如果未能解决你的问题,请参考以下文章

Matlab MEX-函数副作用

如何在不复制数据的情况下将 OpenCV Mat 发送到 MATLAB 工作区?

基于 Matlab C 的 Mex 文件,套接字未运行

如何以异步方式有效地将变量从 Matlab 传递到 GPU?

如何传递 matlab::data::TypedArray<double> 作为指针在 MATLAB mex 文件中构造犰狳矩阵?

升级到 macOS Mojave 后,MATLAB 不再卸载 MEX 文件