【发布时间】:2011-08-01 23:40:28
【问题描述】:
我在我创建的一个类中有一个属性,该属性当前具有与之关联的不必要的 get 函数。我最初让它在返回值之前做一些有用的事情,但现在我只需要属性值,所以 get 函数已经简化为:
function value = get.error(obj) value = obj.error; end
现在,由于这段代码完全是多余的,所以我决定一起删除 get 函数,但这会导致在我的代码中的“错误”属性所在的部分中难以置信速度变慢重复访问。
在这部分代码中,分析器没有明确说缺少 get 函数是问题的原因(它说所有时间都浪费在了'for' 循环),但是当我重新添加功能上无用的代码时,性能问题就消失了。
为什么删除这个无用的 get 函数会减慢我的代码速度?
编辑:我已经将问题隔离到足以发布一些代码示例。
这是一个有问题的方法调用的虚拟版本:
这是没有无用 getter 的代码配置文件:
还有神奇的无用吸气剂:
请注意,性能要求如下:
在计算集中使用我的“池”对象的某些属性来设置任何变量。 '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
【问题讨论】:
-
令人惊讶。通常,吸气剂会使字段访问速度变慢,而不是更快。也许它正在影响 JIT 优化。您是否也可以包含显示访问权限的客户端代码 sn-p 吗?它只是在做
foo.error吗?那个慢循环是在课堂内还是在课堂外?有和没有 getter 的调用速度有多快? (尝试在循环中仅对属性访问进行基准测试。)任何子类或超类?error中存储的是什么类型的值,字段属性是什么?你能用最小的类重现它吗?或者在你的课程中包含完整的源代码和缓慢的循环? -
对不起,我之前没有包含代码;当时功能太大而无用。我已将问题隔离为一个较小的假函数并发布了代码。
-
奇怪。我没有线索。也许在没有吸气剂的情况下它会产生额外的“垃圾”,但我不知道为什么。您使用的是什么 Matlab 版本、操作系统和架构 (x86/x64)?
-
我使用的是 Matlab 7.12.0 (R2011a),我相信它是最新版本。我正在运行 64 位 Windows 7 x86。奇怪的是没有getter,它应该使用默认值,所以我不知道为什么垃圾会有任何区别:(。也许声明允许一些JIT编译魔法?
-
您的池对象还有哪些其他字段?它们中有多少数据(作为字节和 mxarray 的数量)?这些字段中有任何单元格数组吗?
标签: performance oop matlab profiling getter