Matlab Get Property 函数导致性能问题
我创建的类之一中有一个属性,当前有一个与其关联的不必要的 get 函数。我最初让它在返回值之前做有用的事情,但现在我只需要属性值,因此 get 函数已简化为:
函数值 = get.error(obj) 值 = obj.error; 结尾
现在,鉴于此代码完全多余,我决定将 get 函数全部删除,但这会导致代码中重复访问“error”属性的部分出现令人难以置信的速度减慢。
在这一段代码中,探查器并没有明确指出缺少的 get 函数是问题的原因(它表示所有时间都浪费在了“for”的“末尾”)循环),但是当我重新添加功能上无用的代码时,性能问题就消失了。
为什么删除这个无用的 get 函数会减慢我的代码速度?
编辑:我已经隔离了足够的问题来发布一些代码示例。
这是有问题的方法调用的虚拟版本:
这是没有无用 getter 的代码配置文件:
并使用神奇的无用吸气剂:
请注意,性能要求如下:
使用我的 ' 的某些属性计算中的 pool' 对象设置为任何变量。 “error”属性引起了我的注意,但是在相同情况下,所有属性都会发生该错误。
计算涉及任何内容,甚至“.* 0”都会导致速度减慢,但设置的单个项不会减慢(例如 obj.pools(i).delta = obj.pools(i).error)
编辑 2:
这是完整的台球课程;也许会有帮助:
classdef pool < handle
properties
name;
unit_count;
activation;
net_input = 0;
%all projections now incoming
projections = [];
error; % same is dEd net for rbp
target;
clamped_error = false;
delta;
clamped_activation = 0; %0 no clamp, 1 soft clamp, 2 hard clamp
copyback = false;
copy_from;
type = 'hidden';
activation_history;
error_history;
end
methods
function obj = pool(name,count,type,copy_from)
obj.name = name;
assignin('caller', name, obj);
obj.unit_count = count;
obj.error = zeros(1,count);
obj.target = zeros(1,count);
obj.delta = zeros(1,count);
obj.activation = zeros(1,count);
obj.net_input = zeros(1,count);
obj.activation_history(:,1) = zeros(1,count);
obj.error_history(:,1) = zeros(1,count);
if nargin > 2
obj.type = type;
if nargin == 4
obj.clamped_activation = 2;
obj.activation = ones(1,count)/2;
obj.copy_from = copy_from;
obj.copyback = true;
end
else
obj.type = 'hidden';
end
switch obj.type
case 'input'
obj.clamped_activation = 2;
case 'output'
obj.clamped_error = true;
case 'bias'
obj.clamped_activation = 2;
obj.activation = 1;
case 'hidden'
end
end
function proj = connect(obj,send_pool,proj_var)
%see if you need a new projection or if the user provided one
if nargin == 2
proj = projection(obj, send_pool);
else
proj = proj_var;
end
obj.projections = [obj.projections struct('from',send_pool,'using',proj)];
end
function value = get.error(obj)
value = obj.error;
end
end
end
I have a property in one of the classes I created that currently has an unnecessary get function associated with it. I initially made it to do useful things before returning the value, but now I just need the property value, so the get function has been reduced to this:
function value = get.error(obj) value = obj.error; end
Now, seeing as this code is completely redundant, I decided to delete the get function all together, but this leads to an incredible slowdown in one section of my code where the 'error' property is accessed repeatedly.
In this section of code, the profiler doesn't explicitly say that the missing get function is the cause of the problem (it says all of the time is wasted at the 'end' of a 'for' loop), but when I add the functionally useless code back in, the performance problem goes away.
Why would deleting this useless get function slow down my code?
EDIT: I've isolated the problem enough to post some code samples.
Here's a dummy version of the method call that has the problem:
Here's the code profile without the useless getter:
and with the magical useless getter:
Note that the requires for the performance appear to be as follows:
use some property of my 'pool' object in a computation set to any variable. The 'error' property is the one that caught my attention, but the bug happens with all properties in the same situation.
the computation involves anything, even '.* 0' causes this slowdown, but a single term being set is slowdown free (e.g. obj.pools(i).delta = obj.pools(i).error)
EDIT 2:
Here's the full pool class; perhaps it'll help:
classdef pool < handle
properties
name;
unit_count;
activation;
net_input = 0;
%all projections now incoming
projections = [];
error; % same is dEd net for rbp
target;
clamped_error = false;
delta;
clamped_activation = 0; %0 no clamp, 1 soft clamp, 2 hard clamp
copyback = false;
copy_from;
type = 'hidden';
activation_history;
error_history;
end
methods
function obj = pool(name,count,type,copy_from)
obj.name = name;
assignin('caller', name, obj);
obj.unit_count = count;
obj.error = zeros(1,count);
obj.target = zeros(1,count);
obj.delta = zeros(1,count);
obj.activation = zeros(1,count);
obj.net_input = zeros(1,count);
obj.activation_history(:,1) = zeros(1,count);
obj.error_history(:,1) = zeros(1,count);
if nargin > 2
obj.type = type;
if nargin == 4
obj.clamped_activation = 2;
obj.activation = ones(1,count)/2;
obj.copy_from = copy_from;
obj.copyback = true;
end
else
obj.type = 'hidden';
end
switch obj.type
case 'input'
obj.clamped_activation = 2;
case 'output'
obj.clamped_error = true;
case 'bias'
obj.clamped_activation = 2;
obj.activation = 1;
case 'hidden'
end
end
function proj = connect(obj,send_pool,proj_var)
%see if you need a new projection or if the user provided one
if nargin == 2
proj = projection(obj, send_pool);
else
proj = proj_var;
end
obj.projections = [obj.projections struct('from',send_pool,'using',proj)];
end
function value = get.error(obj)
value = obj.error;
end
end
end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这听起来像是 Matlab JIT 或解释器的怪异。
您可能正在查看与 MCOS 内存管理相关的 Matlab 错误,如 Statistics Toolbox 的数据集数组索引非常慢。在某些情况下,该错误看起来会在引用对象的字段时导致对象的虚假深度复制。如果池对象中有元胞数组或其他复杂结构,则可能会导致类似的行为 - 它们会被复制到新变量中,并且释放成本可能会显示在“末尾”。
我能够在几个 Matlab 版本中重现类似的令人惊讶的缓慢结果。但我无法表现出与吸气剂的存在有任何区别。
文件 fooclass.m。
文件 Looper.m。
重现:
这是在我的 64 位 Windows 7 上的 R2011a(预发行版)上。速度很慢。时间与 bigjunk 的大小成正比,分析器表示几乎全部发生在
p = obj.pools
行上。这表明对象引用导致了复制,而不是像预期那样使用写时复制优化。或者它正在遍历对象图,或者其他什么。您的代码可能会发生类似的情况。可能最好将其归因于解释器的怪异,如果它使您的代码更快,则将 getter 保留在那里,然后等待下一个版本中的修复。听起来值得作为错误报告提交给 MathWorks。
This sounds like Matlab JIT or interpreter weirdness.
You may be looking at a Matlab bug related to MCOS memory management, like that discussed in Dataset array indexing is very slow with Statistics Toolbox. That bug looks like it causes spurious deep copying of objects when referencing their fields in some cases. If you have cell arrays or other complex structures in your pool objects, that could cause similar behavior - they get copied in to new variables, and maybe the deallocation cost is showing up at the "end".
I was able to reproduce similar surprising slow results in several Matlab versions. But I wasn't able to show any difference from the presence of a getter.
File fooclass.m.
File looper.m.
To reproduce:
That's on my R2011a (prerelease) on 64-bit Windows 7. That's slow. The time is proportional to the size of bigjunk, and the profiler says it almost all happens on the
p = obj.pools
line. This suggests that the object reference is causing a copy instead of using the copy-on-write optimization like it's supposed to. Or it's walking the object graph, or something. Something similar could be going on with your code.Might be best to just chalk it up to interpreter weirdness, leave the getter in there if it makes your code faster, and wait for a fix in the next release. Sounds worth submitting to MathWorks as a bug report.