简而言之:是否有一种优雅的方式来限制匿名函数的范围,或者在这个例子中是否有Matlab破坏?
我有一个函数创建一个在管网解算器中使用的函数句柄.它接受一个网络状态作为输入,其中包括有关管道及其连接的信息(如果必须,还包括边和顶点),构造一个大字符串,在函数形式时将返回一个大矩阵,并"evals"该字符串以创建句柄.
function [Jv,...] = getPipeEquations(Network)
... %// some stuff happens here
Jv_str = ['[listConnected(~endNodes,:)',...
' .* areaPipes(~endNodes,:);\n',...
anotherLongString,']'];
Jv_str = sprintf(Jv_str); %// This makes debugging the string easier
eval(['Jv = @(v,f,rho)', Jv_str, ';']);
Run Code Online (Sandbox Code Playgroud)
这个函数按预期工作,但每当我需要保存包含此函数句柄的后续数据结构时,它需要一个可笑的内存量(150MB) - 巧合的是在创建此函数时整个Matlab工作区(~~) 150MB).这个函数处理的变量需要来自getPipeEquations工作区并不是特别大,但是当我检查函数句柄时,更疯狂的是:
>> f = functions(Network.jacobianFun)
f =
function: [1x8323 char]
type: 'anonymous'
file: '...\pkg\+adv\+pipe\getPipeEquations.m'
workspace: {2x1 cell}
Run Code Online (Sandbox Code Playgroud)
...工作区字段包含getPipeEquations具有的所有内容(顺便说一句,它不是整个Matlab工作区).
如果我改为将eval语句移动到子函数以试图强制范围,则句柄将更加紧凑(~1MB):
function Jv = getJacobianHandle(Jv_str,listConnected,areaPipes,endNodes,D,L,g,dz)
eval(['Jv = @(v,f,rho)', Jv_str, ';']);
Run Code Online (Sandbox Code Playgroud)
这是预期的行为吗?是否有更优雅的方式来限制此匿名函数的范围?
作为附录,当我多次运行包含此函数的模拟时,清除工作空间变得非常缓慢,这可能与Matlab处理函数及其工作空间有关,也可能与之无关.
我有一个用Matlab编写的大型仿真套件,但是由于担心与其他内部项目的更好接口(以及执行速度),我正在考虑将一些功能转移到.NET并从Matlab中调用这些对象.什么是与调用.NET对象相关的开销内 Matlab的?
这里是关于Matlab OO的一个很好的讨论,它没有谈论.NET
编辑:简要研究
我在Matlab中自行运行了一个快速测试,在不同对象中进行简单访问和赋值操作,包括正式的Matlab对象(R2011b),Java和.NET每次调用1,000,000次.方法调用是指内部循环,属性/字段调用是指从Matlab访问公共字段并在Matlab中循环.最后的结果让我感到困惑,因为.NET的开销远高于Java,但实际运行时间约为一半.到底是怎么回事?
Access(s) Assign(s) Type of object/call --- MATLAB --- 0.003361 0.004268 'myObj.field' 0.003403 0.004263 'myStruct.field' 0.003376 0.003392 'myVar' 0.152629 0.303579 'myHandleObj.field' 25.79159 - 'TestConstant.const' 0.003384 - 'myTestConstant.const' (instance) 0.006794 0.008689 'TestObj.methods' 0.157509 0.303357 'TestHandleObj.methods' --- NON-MATLAB --- 10.70006 16.42527 'JavaObj fields' 0.005063 0.005441 'JavaObj methods' 43.49988 43.96159 'NetObj fields' 0.002194 0.002306 'NetObj methods'