Matlab 就地编辑以防止通过写时复制进行重新分配

Matlab 就地编辑以防止通过写时复制进行重新分配,matlab,mex,copy-on-write,Matlab,Mex,Copy On Write,我想将功能包装到一个函数中,在这种情况下,增加一个可能很大的矩阵中的第一个元素: >tic;A=零(100000000,1);toc; 运行时间为0.324779秒。 >>抽搐;A(1)=A(1)+1;toc;A(1) 运行时间为0.000011秒。 ans= 1. 考虑到增量将是一个更复杂、代码密集的操作。因此,我决定将其包装在一个函数中: 功能A=速度测试(A) A(1)=A(1)+1; 结束 >tic;A=速度测试(A);toc;A(1) 运行时间为0.366090秒。 ans= 2.

我想将功能包装到一个函数中,在这种情况下,增加一个可能很大的矩阵中的第一个元素:

>tic;A=零(100000000,1);toc;
运行时间为0.324779秒。
>>抽搐;A(1)=A(1)+1;toc;A(1)
运行时间为0.000011秒。
ans=
1.
考虑到增量将是一个更复杂、代码密集的操作。因此,我决定将其包装在一个函数中:

功能A=速度测试(A)
A(1)=A(1)+1;
结束
>tic;A=速度测试(A);toc;A(1)
运行时间为0.366090秒。
ans=
2.
这强烈表明A是复制的,但它不应该是必需的;也就是说,Matlab可以检测到(1)A在同一语句中被覆盖,(2)A的数据没有与另一个变量共享。然而,它显然没有这样做

因此,解决方案是按照OP的建议进行黑客攻击:

#包括
#包括
#包括
void mexFunction(int-nargout,mxArray*argout[],int-nargin,const-mxArray*argin[]){
MXUNSHARARRAY(常数转换(精氨酸[0]),真);
double*数据=(double*)mxGetData(argin[0]);
数据[0]=数据[0]+1;
}
但是,这会导致错误:

mexSpeedTest.cpp: In function ‘void mexFunction(int, mxArray**, int, const mxArray**)’:
mexSpeedTest.cpp:7:54: error: ‘mxUnshareArray’ was not declared in this scope
MXUNSHARARRAY(常数转换(精氨酸[0]),真)

我假设在Matlab8.1.0.604(R2013a)中删除了mxUnshareArray;我的版本。我也可以简单地删除该行,这很快就能工作:

>> tic; mexSpeedTest(A); toc; A(1)
Elapsed time is 0.000061 seconds.
ans =
     3
>> 
然而,它打破了Matlab的规则,即具有不可变的右手值。不幸的是,我不愿意放弃通过在函数中包装功能来清理代码,也不愿意允许无用的减速。请注意,我在AF循环中使用了函数,在这里我已经尝试用C++和MEX优化部件。 一种解决方案可以是通过OO解决,即:

classdef incrementabledata
速度更快,但与未包装的裸体增量不相等;我假设数据没有被复制。此外,它还有很多样板代码

tic;AA=递增数据();toc
运行时间为0.005504秒。
抽搐;AA.增量();toc;AA.A(1)
运行时间为0.003939秒。
ans=
1.
我的问题可以归结为以下几点:(1)是否可以在Matlab中进行某种引用传递构造,或者编辑输入参数并将其传递到输出而不进行复制?(2)为什么mxUnshareArray不存在?和(3)如果使用mxUnshareArray,函数内部的版本是否会取消共享,从而与工作区中的版本不同,不允许“模拟”通过引用传递?

我这样问是因为我想要速度和干净的代码:)

答案@Peters解决方案有效。我想补充一点,它似乎并没有复制所有数据,这是以下代码:

#包括
#包括
#包括
外部“C”bool mxUnshareArray(mxArray*阵列ptr,bool noDeepCopy);
void mexFunction(int-nargout,mxArray*argout[],int-nargin,const-mxArray*argin[]){
MXUNSHARARRAY(常数转换(精氨酸[0]),真);
double*数据=(double*)mxGetData(argin[0]);
数据[0]=数据[0]+1;
}
这一速度的结果是:

>> tic; unsharedMexSpeedTest(A); toc; A(1)
Elapsed time is 0.000119 seconds.
ans =
    4
仍然比裸溶液慢约10倍。我假设这是由于函数调用开销造成的,并且当实际操作占用更多CPU周期时,相对速度损失较小。

mxUnshareArray()
未记录,这意味着原型未在MATLAB头文件中声明。但符号应该仍然可用。您只需要自己编写函数的原型,以便编译器知道如何形成调用。将其放在文件顶部(在全局范围内),您需要将其称为:

extern "C" bool mxUnshareArray(mxArray *array_ptr, bool noDeepCopy);
“unshare”将阻止它做非常奇怪的事情:

B = A;
mexSpeedTest(A);
A(1)
B(1)

被视为
mexSpeedTest
输入的变量正好是A;没有为MEX函数调用制作额外的副本,因此
mxUnshareArray
将执行您想要的操作。

好的一点,我仔细阅读了mxUnshareArray函数定义。这似乎有效,尤其是在问题OP.(3)上的“是”。在OP中添加了一些对此的评论