我想将功能包装在一个函数中,在这种情况下,增加一个可能很大的矩阵中的第一个元素:
>> tic; A=zeros(100000000,1); toc;
Elapsed time is 0.324779 seconds.
>> tic; A(1)=A(1)+1; toc; A(1)
Elapsed time is 0.000011 seconds.
ans =
1
考虑到增量将是一个更复杂、代码密集的操作。因此,我决定将它包装在一个函数中:
function A = speedTest(A)
A(1)=A(1)+1;
end
>> tic; A=speedTest(A); toc; A(1)
Elapsed time is 0.366090 seconds.
ans =
2
这强烈表明 A 被复制了,但它不应该是必要的;即Matlab可以检测到(1)A在同一个语句中被覆盖,(2)A的数据不与另一个变量共享。但是,它显然没有这样做。
因此,一种解决方案是按照此处 OP 的建议进行破解:Working with preallocated arrays in Matlab's mex function
#include <matrix.h>
#include <mex.h>
#include <iostream>
void mexFunction(int nargout, mxArray *argout[], int nargin, const mxArray *argin[]) {
mxUnshareArray(const_cast<mxArray *>(argin[0]), true);
double *data = (double *)mxGetData(argin[0]);
data[0] = data[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
mxUnshareArray(const_cast(argin[0]), true);
我假设在 Matlab 8.1.0.604 (R2013a) 中删除了 mxUnshareArray;我的版本。我也可以简单地删除该行,这很快:
>> tic; mexSpeedTest(A); toc; A(1)
Elapsed time is 0.000061 seconds.
ans =
3
>>
然而,它打破了 Matlab 的右手值不可变的规则。不幸的是,我不愿意放弃通过在函数中包装功能来清理我的代码,也不愿意允许无用的减速。请注意,我在 for 循环中使用该函数,我已经尝试使用 c++ 和 mex 优化部分。
一种解决方案可能是通过 OO 解决它,即:
classdef incrementabledata < handle
properties
A=[]
end
methods
function HB=incrementabledata()
HB.A = zeros(100000000,1);
end
function increment(HB)
HB.A(1)=HB.A(1)+1;
end
end
end
哪个更快,但不如展开的裸增量快;我假设数据没有被复制。此外,它还有很多样板代码。
tic; AA = incrementabledata(); toc
Elapsed time is 0.005504 seconds.
tic; AA.increment(); toc; AA.A(1)
Elapsed time is 0.003939 seconds.
ans =
1
我的问题归结为:(1)是否有可能在 Matlab 中通过引用构造进行某种传递,或者在不复制输入参数的情况下编辑并将其传递给输出?(2)为什么没有mxUnshareArray?(3)如果我使用 mxUnshareArray,函数内的 A 版本是否会被取消共享,从而与工作区中的版本不同,从而不允许“模拟”通过引用传递?
我问是因为我想要速度和干净的代码:)
答案@Peters 解决方案是有效的。我想补充一点,它似乎并没有复制所有数据,即这段代码:
#include <matrix.h>
#include <mex.h>
#include <iostream>
extern "C" bool mxUnshareArray(mxArray *array_ptr, bool noDeepCopy);
void mexFunction(int nargout, mxArray *argout[], int nargin, const mxArray *argin[]) {
mxUnshareArray(const_cast<mxArray *>(argin[0]), true);
double *data = (double *)mxGetData(argin[0]);
data[0] = data[0]+1;
}
导致这个速度:
>> tic; unsharedMexSpeedTest(A); toc; A(1)
Elapsed time is 0.000119 seconds.
ans =
4
这仍然比裸解决方案慢约 10 倍。我假设这是由于函数调用开销造成的,并且当实际操作需要更多 CPU 周期时,相对速度损失较小。