MATLAB OOP速度慢还是我做错了什么?

MATLAB OOP速度慢还是我做错了什么?,matlab,oop,profiling,benchmarking,matlab-class,Matlab,Oop,Profiling,Benchmarking,Matlab Class,我正在试验,作为开始,我模仿了我的C++的Logger类,并将我所有的string助手函数都放在一个string类中,我认为能够做像a+b,a==b,a.find(b)这样的事情会很好 在strcat(a,b),strcmp(a,b)中,检索strfind(a,b)的第一个元素,等等 问题:经济放缓 我使用了上面的东西,立即注意到速度急剧放缓。我是做错了(这当然是可能的,因为我的MATLAB经验相当有限),还是MATLAB的OOP只是引入了大量的开销 我的测试用例 下面是我对字符串所做的简单测试

我正在试验,作为开始,我模仿了我的C++的Logger类,并将我所有的string助手函数都放在一个string类中,我认为能够做像
a+b
a==b
a.find(b)
这样的事情会很好 在strcat(a,b),
strcmp(a,b)
中,检索
strfind(a,b)
的第一个元素,等等

问题:经济放缓

我使用了上面的东西,立即注意到速度急剧放缓。我是做错了(这当然是可能的,因为我的MATLAB经验相当有限),还是MATLAB的OOP只是引入了大量的开销

我的测试用例

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

注意:不要在实际代码中编写这样的字符串类!Matlab现在有一个原生的
字符串
数组类型,您应该改用它

结果,以与上述相同的方式收集:

atest 0.004秒,ctest中0.001秒

b测试0.060秒,在util.ctest中测试0.014秒


那么,所有这些开销是不是都来自于MATLAB花时间查找其OOP实现的定义,而对于直接位于路径中的函数,这些开销并不存在呢?

handle类还有一个额外的开销,就是为了清理而跟踪对自身的所有引用


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

我使用OO MATLAB已经有一段时间了,最后发现了类似的性能问题

简单的回答是:是的,MATLAB的OOP有点慢。有大量的方法调用开销,比主流OO语言要高,对此您无能为力。部分原因可能是惯用的MATLAB使用“矢量化”代码来减少方法调用的数量,并且每次调用的开销不是一个高优先级

我通过编写各种类型的函数和方法的“nop”函数来测试性能。下面是一些典型的结果

>> call_nops Computer: PCWIN Release: 2009b Calling each function/method 100000 times nop() function: 0.02261 sec 0.23 usec per call nop1-5() functions: 0.02182 sec 0.22 usec per call nop() subfunction: 0.02244 sec 0.22 usec per call @()[] anonymous function: 0.08461 sec 0.85 usec per call nop(obj) method: 0.24664 sec 2.47 usec per call nop1-5(obj) methods: 0.23469 sec 2.35 usec per call nop() private function: 0.02197 sec 0.22 usec per call classdef nop(obj): 0.90547 sec 9.05 usec per call classdef obj.nop(): 1.75522 sec 17.55 usec per call classdef private_nop(obj): 0.84738 sec 8.47 usec per call classdef nop(obj) (m-file): 0.90560 sec 9.06 usec per call classdef class.staticnop(): 1.16361 sec 11.64 usec per call Java nop(): 2.43035 sec 24.30 usec per call Java static_nop(): 0.87682 sec 8.77 usec per call Java nop() from Java: 0.00014 sec 0.00 usec per call MEX mexnop(): 0.11409 sec 1.14 usec per call C nop(): 0.00001 sec 0.00 usec per call 我认为结果是:

  • MCOS/classdef方法更快。现在,只要使用<代码> FO(OBJ)语法,成本与旧样式类相当。因此,在大多数情况下,方法速度不再是坚持使用旧式类的理由。(荣誉,MathWorks!)
  • 将函数放在名称空间中会使它们变慢。(在R2011b中不是新的,只是在我的测试中是新的。)
更新:R2014a 我重新构建了基准测试代码,并在R2014a上运行它

Matlab R2014a on PCWIN64 Matlab 8.3.0.532 (R2014a) / Java 1.7.0_11 on PCWIN64 Windows 7 6.1 (eilonwy-win7) Machine: Core i7-3615QM CPU @ 2.30GHz, 4 GB RAM (VMware Virtual Platform) nIters = 100000 Operation Time (µsec) nop() function: 0.14 nop() subfunction: 0.14 @()[] anonymous function: 0.69 nop(obj) method: 3.28 nop() private fcn on @class: 0.14 classdef nop(obj): 5.30 classdef obj.nop(): 10.78 classdef pivate_nop(obj): 4.88 classdef class.static_nop(): 11.81 classdef constant: 4.18 classdef property: 1.18 classdef property with getter: 19.26 +pkg.nop() function: 4.03 +pkg.nop() from inside +pkg: 4.16 feval('nop'): 2.31 feval(@nop): 0.22 eval('nop'): 59.46 Java obj.nop(): 26.07 Java nop(obj): 3.72 Java feval('nop',obj): 9.25 Java Klass.staticNop(): 10.54 Java obj.nop() from Java: 0.01 MEX mexnop(): 0.91 builtin j(): 0.02 struct s.foo field access: 0.14 isempty(persistent): 0.00 更新:R2018a 这是R2018a的结果。这并不是我们在R2015b中引入新执行引擎时看到的巨大飞跃,但它仍然是一个明显的逐年改进。值得注意的是,匿名函数句柄的速度大大加快

Matlab R2018a on MACI64 Matlab 9.4.0.813654 (R2018a) / Java 1.8.0_144 on MACI64 Mac OS X 10.13.5 (eilonwy) Machine: Core i7-3615QM CPU @ 2.30GHz, 16 GB RAM nIters = 100000 Operation Time (µsec) nop() function: 0.03 nop() subfunction: 0.04 @()[] anonymous function: 0.16 classdef nop(obj): 0.16 classdef obj.nop(): 0.17 classdef pivate_nop(obj): 0.16 classdef class.static_nop(): 0.03 classdef constant: 0.16 classdef property: 0.13 classdef property with getter: 0.39 +pkg.nop() function: 0.02 +pkg.nop() from inside +pkg: 0.02 feval('nop'): 15.62 feval(@nop): 0.43 eval('nop'): 32.08 Java obj.nop(): 28.77 Java nop(obj): 8.02 Java feval('nop',obj): 21.85 Java Klass.staticNop(): 45.49 Java obj.nop() from Java: 0.03 MEX mexnop(): 3.54 builtin j(): 0.10 struct s.foo field access: 0.16 isempty(persistent): 0.07 基于MACI64的Matlab R2018a MACI64 Mac OS X 10.13.5(eilonwy)上的Matlab 9.4.0.813654(R2018a)/Java 1.8.0144 机器:核心i7-3615QM CPU@2.30GHz,16GB RAM 硝酸盐=100000 操作时间(微秒) nop()函数:0.03 nop()子函数:0.04 @()[]匿名函数:0.16 类别定义nop(obj):0.16 classdef obj.nop():0.17 类别定义pivate_nop(obj):0.16 classdef class.static_nop():0.03 classdef常量:0.16 classdef属性:0.13 带有getter的classdef属性:0.39 +函数:0.02 +pkg.nop()从内部+pkg:0.02 feval('nop'):15.62 feval(@nop):0.43 评估('nop'):32.08 Java obj.nop():28.77 Java nop(obj):8.02 JavaFeval('nop',obj):21.85 Java Klass.staticNop():45.49 Java:0.03中的Java obj.nop() MEX mexnop():3.54 内置j():0.10 结构s.foo字段访问:0.16 isempty(持续):0.07 更新:R2018b和R2019a:无变化 没有重大变化。我不想费心把测试结果包括在内

基准测试的源代码
我已经将这些基准测试的源代码放在GitHub上,在MIT许可下发布

OO性能在很大程度上取决于所使用的MATLAB版本。我不能对所有版本发表评论,但根据经验,2012a比2010版本有了很大改进。没有基准,因此没有数字可提供。我的代码是专门使用handle类编写并在2012a下编写的,在早期版本下根本不会运行。

实际上,您的代码没有问题,但Matlab有问题。我认为这是一种玩弄的样子。编译类代码只会增加开销。 我已经用简单类point(一次作为句柄)和另一个(一次作为值类)进行了测试

结果 t1=

12.0212%手柄

t2=

12.0042%价值

t3=

t4=


因此,为了提高性能,请避免使用OOP而不是结构化,这是对变量进行分组的好选择

谢谢您的提问!Matlab堆(OOP/闭包)的性能多年来一直困扰着我,请参阅。我真的很好奇MatlabDoug/Loren/MikeKatz会对你的帖子做出什么回应。^这是一篇有趣的文章。@MatlabDoug:也许你的同事Mike Karr可以评论OP?读者也应该查看这篇最近的博文(由Dave Foti撰写)讨论R2012a最新版本中的OOP性能:一个简单的代码结构敏感性示例,其中子元素的方法调用被从循环中取出<代码>对于i=1:this.get\n\u数量()如果(strcmp(id,this.get\u数量)ix=i;结束需要2.2秒,w Arch: PCWIN Release: 2011b Machine: R2011b, Windows XP, 8x Core i7-2600 @ 3.40GHz, 3 GB RAM, NVIDIA NVS 300 Doing each operation 100000 times style total µsec per call nop() function: 0.01578 0.16 nop(), 10x loop unroll: 0.01477 0.15 nop(), 100x loop unroll: 0.01518 0.15 nop() subfunction: 0.01559 0.16 @()[] anonymous function: 0.06400 0.64 nop(obj) method: 0.28482 2.85 nop() private function: 0.01505 0.15 classdef nop(obj): 0.43323 4.33 classdef obj.nop(): 0.81087 8.11 classdef private_nop(obj): 0.32272 3.23 classdef class.staticnop(): 0.88959 8.90 classdef constant: 1.51890 15.19 classdef property: 0.12992 1.30 classdef property with getter: 1.39912 13.99 +pkg.nop() function: 0.87345 8.73 +pkg.nop() from inside +pkg: 0.80501 8.05 Java obj.nop(): 1.86378 18.64 Java nop(obj): 0.22645 2.26 Java feval('nop',obj): 0.52544 5.25 Java Klass.static_nop(): 0.35357 3.54 Java obj.nop() from Java: 0.00010 0.00 MEX mexnop(): 0.08709 0.87 C nop(): 0.00001 0.00 j() (builtin): 0.00251 0.03 Matlab R2014a on PCWIN64 Matlab 8.3.0.532 (R2014a) / Java 1.7.0_11 on PCWIN64 Windows 7 6.1 (eilonwy-win7) Machine: Core i7-3615QM CPU @ 2.30GHz, 4 GB RAM (VMware Virtual Platform) nIters = 100000 Operation Time (µsec) nop() function: 0.14 nop() subfunction: 0.14 @()[] anonymous function: 0.69 nop(obj) method: 3.28 nop() private fcn on @class: 0.14 classdef nop(obj): 5.30 classdef obj.nop(): 10.78 classdef pivate_nop(obj): 4.88 classdef class.static_nop(): 11.81 classdef constant: 4.18 classdef property: 1.18 classdef property with getter: 19.26 +pkg.nop() function: 4.03 +pkg.nop() from inside +pkg: 4.16 feval('nop'): 2.31 feval(@nop): 0.22 eval('nop'): 59.46 Java obj.nop(): 26.07 Java nop(obj): 3.72 Java feval('nop',obj): 9.25 Java Klass.staticNop(): 10.54 Java obj.nop() from Java: 0.01 MEX mexnop(): 0.91 builtin j(): 0.02 struct s.foo field access: 0.14 isempty(persistent): 0.00 Matlab R2015b on PCWIN64 Matlab 8.6.0.267246 (R2015b) / Java 1.7.0_60 on PCWIN64 Windows 8 6.2 (nanit-shaked) Machine: Core i7-4720HQ CPU @ 2.60GHz, 16 GB RAM (20378) nIters = 100000 Operation Time (µsec) nop() function: 0.04 nop() subfunction: 0.08 @()[] anonymous function: 1.83 nop(obj) method: 3.15 nop() private fcn on @class: 0.04 classdef nop(obj): 0.28 classdef obj.nop(): 0.31 classdef pivate_nop(obj): 0.34 classdef class.static_nop(): 0.05 classdef constant: 0.25 classdef property: 0.25 classdef property with getter: 0.64 +pkg.nop() function: 0.04 +pkg.nop() from inside +pkg: 0.04 feval('nop'): 8.26 feval(@nop): 0.63 eval('nop'): 21.22 Java obj.nop(): 14.15 Java nop(obj): 2.50 Java feval('nop',obj): 10.30 Java Klass.staticNop(): 24.48 Java obj.nop() from Java: 0.01 MEX mexnop(): 0.33 builtin j(): 0.15 struct s.foo field access: 0.25 isempty(persistent): 0.13 Matlab R2018a on MACI64 Matlab 9.4.0.813654 (R2018a) / Java 1.8.0_144 on MACI64 Mac OS X 10.13.5 (eilonwy) Machine: Core i7-3615QM CPU @ 2.30GHz, 16 GB RAM nIters = 100000 Operation Time (µsec) nop() function: 0.03 nop() subfunction: 0.04 @()[] anonymous function: 0.16 classdef nop(obj): 0.16 classdef obj.nop(): 0.17 classdef pivate_nop(obj): 0.16 classdef class.static_nop(): 0.03 classdef constant: 0.16 classdef property: 0.13 classdef property with getter: 0.39 +pkg.nop() function: 0.02 +pkg.nop() from inside +pkg: 0.02 feval('nop'): 15.62 feval(@nop): 0.43 eval('nop'): 32.08 Java obj.nop(): 28.77 Java nop(obj): 8.02 Java feval('nop',obj): 21.85 Java Klass.staticNop(): 45.49 Java obj.nop() from Java: 0.03 MEX mexnop(): 3.54 builtin j(): 0.10 struct s.foo field access: 0.16 isempty(persistent): 0.07
    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
0.5489  % vector
0.0707 % structure