MATLAB OOP运行缓慢还是我做错了什么?

时间:2009-11-07 15:36:43

标签: matlab oop profiling benchmarking matlab-class

我正在尝试MATLAB OOP,作为一个开始,我模仿我的C ++的Logger类,并且我将所有的字符串辅助函数放在String类中,认为它会很棒能够做a + ba == ba.find( b )之类的事情 strcat( a b )strcmp( a, b ),检索strfind( a, b )的第一个元素等

问题:放缓

我将上述内容用于使用,并立即注意到剧烈减速。我做错了(由于我的MATLAB经验相当有限,这当然是可能的),还是MATLAB的OOP只是引入了很多开销?

我的测试用例

这是我为字符串做的简单测试,基本上只是附加一个字符串并再次删除附加部分:

classdef String < handle
  ....
  properties
    stringobj = '';
  end
  function o = plus( o, b )
    o.stringobj = [ o.stringobj b ];
  end
  function n = Length( o )
    n = length( o.stringobj );
  end
  function o = SetLength( o, n )
    o.stringobj = o.stringobj( 1 : n );
  end
end

function atest( a, b ) %plain functions
  n = length( a );
  a = [ a b ];
  a = a( 1 : n );

function btest( a, b ) %OOP
  n = a.Length();
  a = a + b;
  a.SetLength( n );

function RunProfilerLoop( nLoop, fun, varargin )
  profile on;
  for i = 1 : nLoop
    fun( varargin{ : } );
  end
  profile off;
  profile report;

a = 'test';
aString = String( 'test' );
RunProfilerLoop( 1000, @(x,y)atest(x,y), a, 'appendme' );
RunProfilerLoop( 1000, @(x,y)btest(x,y), aString, 'appendme' );

结果

1000次迭代的总时间(秒):

  

btest 0.550(String.SetLength 0.138,String.plus 0.065,String.Length 0.057)

     

atest 0.015

记录器系统的结果同样为:1000次呼叫的0.1秒 在内部使用String类时,对我的系统进行1000次调用,到frpintf( 1, 'test\n' ),7(!)秒(好吧,它有更多的逻辑,但要与C ++进行比较:我的系统的开销使用{输出端的{1}}和std::string( "blah" )与普通std::cout的顺序为1毫秒。)

查找类/包函数时只是开销吗?

由于MATLAB被解释,它必须在运行时查找函数/对象的定义。所以我想知道在查找类或包函数与路径中的函数时可能会有更多的开销。我试着测试一下,它只是变得陌生。为了排除类/对象的影响,我比较了调用路径中的函数与函数中的函数:

std::cout << "blah"

结果,收集方式如上:

  

atest 0.004秒,ctest为0.001秒

     

btest 0.060秒,在util.ctest中为0.014秒

因此,所有这些开销都来自MATLAB花费时间查找其OOP实现的定义,而这种开销不适用于直接在路径中的函数吗?

4 个答案:

答案 0 :(得分:209)

答案 1 :(得分:3)

handle类有一个额外的开销,即跟踪所有对自身的引用以进行清理。

在不使用句柄类的情况下尝试相同的实验,看看你的结果是什么。

答案 2 :(得分:1)

OO性能在很大程度上取决于所使用的MATLAB版本。我不能对所有版本发表评论,但从经验中可以看出,2012a比2010版本有了很大改进。没有基准,所以没有数字呈现。我的代码只使用句柄类编写并在2012a下编写,在早期版本中根本不会运行。

答案 3 :(得分:1)

实际上您的代码没有问题,但这是Matlab的一个问题。我认为这是一种玩耍的样子。编译类代码不过是开销。 我用简单的类点(一次作为句柄)和另一个(一次作为值类)

完成了测试
    classdef Pointh < handle
    properties
       X
       Y
    end  
    methods        
        function p = Pointh (x,y)
            p.X = x;
            p.Y = y;
        end        
        function  d = dist(p,p1)
            d = (p.X - p1.X)^2 + (p.Y - p1.Y)^2 ;
        end

    end
end

这是测试

%handle points 
ph = Pointh(1,2);
ph1 = Pointh(2,3);

%values  points 
p = Pointh(1,2);
p1 = Pointh(2,3);

% vector points
pa1 = [1 2 ];
pa2 = [2 3 ];

%Structur points 
Ps.X = 1;
Ps.Y = 2;
ps1.X = 2;
ps1.Y = 3;

N = 1000000;

tic
for i =1:N
    ph.dist(ph1);
end
t1 = toc

tic
for i =1:N
    p.dist(p1);
end
t2 = toc

tic
for i =1:N
    norm(pa1-pa2)^2;
end
t3 = toc

tic
for i =1:N
    (Ps.X-ps1.X)^2+(Ps.Y-ps1.Y)^2;
end
t4 = toc

结果 t1 =

12.0212%处理

t2 =

12.0042%价值

t3 =

0.5489  % vector

t4 =

0.0707 % structure 

因此,为了提高效率,避免使用OOP代替结构是分组变量的好选择