MATLAB OOP가 느리거나 잘못하고 있습니까?
내가 실험하고있어 MATLAB OOP A가 내 C ++의 로거 클래스를 모방 시작으로, 나는이 같은 일을 할 수있는 것이 좋은 것 생각하고, 문자열 클래스에 내 모든 문자열 도우미 기능을 가하고있어 a + b
, a == b
, a.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 사용)
증명 0.015
로거 시스템의 결과는 다음과 같습니다 : frpintf( 1, 'test\n' )
String 클래스를 내부적으로 사용할 때 1000 호출에 대해 0.1 초 , 내 시스템에 1000 호출에 대해 7 (!) 초 (OK, 더 많은 논리가 있지만 C ++과 비교) : 사용 내 시스템의 오버 헤드 std::string( "blah" )
및 std::cout
일반 대 출력측은 std::cout << "blah"
1 밀리 초 정도이다.)
클래스 / 패키지 함수를 찾을 때 오버 헤드입니까?
MATLAB은 해석되므로 런타임시 함수 / 객체의 정의를 찾아야합니다. 그래서 경로에있는 함수 대 클래스 또는 패키지 함수를 찾는 데 훨씬 더 많은 오버 헤드가 관련되어 있는지 궁금합니다. 나는 이것을 시험하려고 노력했고, 그것은 단지 낯선 사람을 얻는다. 클래스 / 객체의 영향을 배제하기 위해 경로의 함수와 패키지의 함수를 호출하는 것을 비교했습니다.
function n = atest( x, y )
n = ctest( x, y ); % ctest is in matlab path
function n = btest( x, y )
n = util.ctest( x, y ); % ctest is in +util directory, parent directory is in path
결과는 위와 같은 방식으로 수집되었습니다.
atest 0.004 sec, ctest에서 0.001 초
util.ctest에서 btest 0.060 초, 0.014 초
MATLAB에서 OOP 구현에 대한 정의를 찾는 데 시간이 걸리는 반면이 오버 헤드는 직접 경로에있는 함수에는 없는가?
나는 한동안 OO MATLAB과 협력하여 비슷한 성능 문제를 보았습니다.
짧은 대답은 그렇습니다. MATLAB의 OOP는 느립니다. 주류 OO 언어보다 높은 메소드 호출 오버 헤드가 있으며 이에 대해 할 수있는 일은 많지 않습니다. 그 이유 중 하나는 관용적 MATLAB이 "벡터화 된"코드를 사용하여 메소드 호출 수를 줄이고 호출 당 오버 헤드가 우선 순위가 높지 않기 때문일 수 있습니다.
나는 아무 것도없는 "nop"함수를 다양한 유형의 함수와 메소드로 작성하여 성능을 벤치마킹했습니다. 다음은 일반적인 결과입니다.
>> call_nops 컴퓨터 : PCWIN 출시 : 2009b 각 함수 / 메소드를 100,000 번 호출 nop () 함수 : 호출 당 0.02261 초 0.23 usec nop1-5 () 함수 : 호출 당 0.02182 초 0.22 usec nop () 하위 함수 : 호출 당 0.02244 초 0.22 usec @ () [] 익명 함수 : 호출 당 0.08461 초 0.85 usec nop (obj) 방법 : 0.24664 초 2.47 회 호출 당 nop1-5 (obj) 메서드 : 호출 당 0.23469 초 2.35 usec nop () 개인 함수 : 호출 당 0.02197 초 0.22 usec classdef nop (obj) : 통화 당 0.90547 초 9.05 usec classdef obj.nop () : 1.75522 초 17.55 호출 당 usec classdef private_nop (obj) : 호출 당 0.84738 초 8.47 usec classdef nop (obj) (m-file) : 0.90560 초 9.06 통화 당 usec classdef class.staticnop () : 1.16361 초 11.64 통화 당 Java nop () : 통화 당 2.43035 초 24.30 usec Java static_nop () : 호출 당 0.87682 초 8.77 usec Java의 Java nop () : 호출 당 0.00014 초 0.00 usec MEX mexnop () : 통화 당 0.11409 초 1.14 usec C nop () : 통화 당 0.00001 초 0.00 usec
R2008a와 R2009b의 결과가 비슷합니다. 32 비트 MATLAB을 실행하는 Windows XP x64에 있습니다.
"Java nop ()"는 M 코드 루프 내에서 호출되는 Java가 아닌 메소드이며 각 호출마다 MATLAB-to-Java 디스패치 오버 헤드를 포함합니다. "Java에서 Java nop ()"는 Java for () 루프에서 호출되는 것과 동일하며 해당 경계 불이익을 일으키지 않습니다. 소금 한 알로 Java 및 C 타이밍을 가져 가십시오. 영리한 컴파일러는 호출을 완전히 최적화 할 수 있습니다.
패키지 범위 지정 메커니즘은 새롭고 classdef 클래스와 거의 동시에 도입되었습니다. 동작이 관련 될 수 있습니다.
몇 가지 임시 결론 :
- 방법은 함수보다 느립니다.
- 새로운 스타일 (classdef) 메소드는 이전 스타일 메소드보다 느립니다.
- 새로운
obj.nop()
구문은nop(obj)
classdef 객체의 동일한 메소드에서도 구문 보다 느립니다 . Java 객체 (표시되지 않음)와 동일합니다. 빨리 가고 싶다면 전화하십시오nop(obj)
. - Windows의 64 비트 MATLAB에서 메서드 호출 오버 헤드가 더 높습니다 (약 2 배). (표시되지 않음)
- MATLAB 메소드 디스패치가 다른 언어보다 느립니다.
이것이 왜 그렇게 말하는지는 내 부분에 대한 추측 일뿐입니다. MATLAB 엔진의 OO 내부는 공개되지 않습니다. MATLAB에는 JIT가 있지만 해석 및 컴파일 된 문제 자체는 아니지만 MATLAB의 타이핑과 구문이 느슨하면 런타임에 더 많은 작업이 필요할 수 있습니다. 예를 들어 "f (x)"가 함수 호출인지 또는 배열에 대한 인덱스인지 구문만으로는 알 수 없습니다. 런타임시 작업 공간의 상태에 따라 다릅니다. MATLAB의 클래스 정의가 연결되어 있기 때문일 수 있습니다 다른 많은 언어들은 그렇지 않은 방식으로 파일 시스템 상태로
그래서 뭘 할건데?
이에 대한 관용적 인 MATLAB 접근 방식은 객체 인스턴스가 배열을 래핑하도록 클래스 정의를 구성하여 코드를 "벡터화"하는 것입니다. 즉, 각 필드는 병렬 배열을 보유합니다 (MATLAB 설명서에서 "평면"구성이라고 함). 각각 스칼라 값을 보유하는 필드가있는 객체의 배열을 갖는 대신, 스스로 배열 인 객체를 정의하고, 메소드가 배열을 입력으로 취하고 필드와 입력에 대해 벡터화 된 호출을 수행하게합니다. 이렇게하면 디스패치 오버 헤드가 병목 현상이되지 않도록 메소드 호출 수가 줄어 듭니다.
MATLAB에서 C ++ 또는 Java 클래스를 흉내내는 것은 아마도 최적이 아닐 것입니다. Java / C ++ 클래스는 일반적으로 객체가 가능한 한 가장 작은 빌딩 블록 (즉, 다양한 클래스)으로 작성되고 배열, 컬렉션 객체 등으로 작성하고 루프로 반복합니다. 빠른 MATLAB 클래스를 만들려면 해당 접근 방식을 안쪽으로 돌리십시오. 필드가 배열 인 더 큰 클래스가 있고 해당 배열에서 벡터화 된 메소드를 호출하십시오.
요점은 배열 처리, 벡터화 수학과 같은 언어의 장점에 따라 코드를 재생하고 약점을 피하는 것입니다.
편집 : 원래 게시물 이후 R2010b 및 R2011a가 나왔습니다. MCOS 호출이 약간 빨라지고 Java 및 이전 스타일 메소드 호출이 느려져 전체적인 그림이 동일 합니다.
편집 : 여기에 함수 호출 타이밍의 추가 테이블과 함께 "경로 감도"에 대한 메모가있었습니다. 여기서 함수 시간은 Matlab 경로의 구성 방법에 의해 영향을 받았지만 특정 네트워크 설정의 수차 인 것처럼 보입니다. 시간. 위의 차트는 시간이 지남에 따라 테스트의 우세한 시간을 반영합니다.
업데이트 : R2011b
편집 (2012 년 2 월 13 일) : R2011b가 종료되었으며 성능 사진이이를 업데이트하기에 충분하도록 변경되었습니다.
아치 : PCWIN 출시 : 2011b 머신 : R2011b, Windows XP, 8x Core i7-2600 @ 3.40GHz, 3GB RAM, NVIDIA NVS 300 각 작업을 100,000 번 수행 통화 당 총 스타일 µsec nop () 함수 : 0.01578 0.16 nop (), 10 배 루프 언롤 : 0.01477 0.15 nop (), 100x 루프 언롤 : 0.01518 0.15 nop () 하위 함수 : 0.01559 0.16 @ () [] 익명 함수 : 0.06400 0.64 nop (obj) 방법 : 0.28482 2.85 nop () 전용 함수 : 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 상수 : 1.51890 15.19 classdef 속성 : 0.12992 1.30 게터가있는 classdef 속성 : 1.39912 13.99 + pkg.nop () 함수 : 0.87345 8.73 + pkg 내부에서 + pkg.nop () : 0.80501 8.05 자바 obj.nop () : 1.86378 18.64 자바 nop (obj) : 0.22645 2.26 자바 feval ( 'nop', obj) : 0.52544 5.25 자바 Klass.static_nop () : 0.35357 3.54 Java의 Java obj.nop () : 0.00010 0.00 MEX mexnop () : 0.08709 0.87 C nop () : 0.00001 0.00 j () (내장) : 0.00251 0.03
나는 이것의 결론은 다음과 같다고 생각한다.
- MCOS / classdef 메소드가 더 빠릅니다.
foo(obj)
구문 을 사용하는 한 비용은 이제 이전 스타일 클래스와 비슷 합니다. 따라서 메소드 속도는 더 이상 대부분의 경우 이전 스타일 클래스를 고수하는 이유가 아닙니다. (Kudos, MathWorks!) - 네임 스페이스에 함수를 넣으면 속도가 느려집니다. (R2011b에서는 새로운 것이 아니라 내 테스트에서는 새로운 것입니다.)
업데이트 : R2014a
벤치마킹 코드를 재구성하고 R2014a에서 실행했습니다.
PCWIN64의 Matlab R2014a PCWIN64 Windows 7 6.1의 Matlab 8.3.0.532 (R2014a) / Java 1.7.0_11 (eilonwy-win7) 머신 : Core i7-3615QM CPU @ 2.30GHz, 4GB RAM (VMware 가상 플랫폼) 니터 = 100000 작동 시간 (µsec) nop () 함수 : 0.14 nop () 하위 함수 : 0.14 @ () [] 익명 함수 : 0.69 nop (obj) 방법 : 3.28 @class의 nop () private fcn : 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 상수 : 4.18 classdef 속성 : 1.18 게터가있는 classdef 속성 : 19.26 + pkg.nop () 함수 : 4.03 + pkg 내부에서 + pkg.nop () : 4.16 feval ( 'nop') : 2.31 feval (@nop) : 0.22 eval ( 'nop') : 59.46 자바 obj.nop () : 26.07 자바 nop (obj) : 3.72 자바 feval ( 'nop', obj) : 9.25 자바 Klass.staticNop () : 10.54 Java의 Java obj.nop () : 0.01 MEX mexnop () : 0.91 내장 j () : 0.02 s.foo 필드 접근 : 0.14 비어 있음 (지속적) : 0.00
업데이트 : R2015b : 객체가 더 빨라졌습니다!
@Shaked가 친절하게 제공 한 R2015b 결과는 다음과 같습니다. 이것은 큰 변화입니다. OOP가 훨씬 빠르며 obj.method()
구문은 method(obj)
기존 OOP 객체보다 빠르며 훨씬 빠릅니다.
PCWIN64의 Matlab R2015b PCWIN64 Windows 8 6.2의 Matlab 8.6.0.267246 (R2015b) / Java 1.7.0_60 (손떨림) 머신 : Core i7-4720HQ CPU @ 2.60GHz, 16GB RAM (20378) 니터 = 100000 작동 시간 (µsec) nop () 함수 : 0.04 nop () 하위 함수 : 0.08 @ () [] 익명 함수 : 1.83 nop (obj) 방법 : 3.15 @class의 nop () private fcn : 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 상수 : 0.25 classdef 속성 : 0.25 게터가있는 classdef 속성 : 0.64 + pkg.nop () 함수 : 0.04 + pkg 내부에서 + pkg.nop () : 0.04 feval ( 'nop') : 8.26 feval (@nop) : 0.63 평가 ( 'nop') : 21.22 자바 obj.nop () : 14.15 자바 nop (obj) : 2.50 자바 feval ( 'nop', obj) : 10.30 자바 Klass.staticNop () : 24.48 Java의 Java obj.nop () : 0.01 MEX mexnop () : 0.33 내장 j () : 0.15 s.foo 필드 접근 : 0.25 비어 있음 (지속적) : 0.13
업데이트 : R2018a
다음은 R2018a 결과입니다. 새로운 실행 엔진이 R2015b에 도입되었을 때 보았던 큰 도약은 아니지만 여전히 매년 개선되고 있습니다. 특히 익명 함수 핸들이 더 빨라졌습니다.
MACI64의 Matlab R2018a 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
Update: R2018b and R2019a: No change
No significant changes. I'm not bothering to include the test results.
Source Code for Benchmarks
I've put the source code for these benchmarks up on GitHub, released under the MIT License. https://github.com/apjanke/matlab-bench
The handle class has an additional overhead from tracking all of references to itself for cleanup purposes.
Try the same experiment without using the handle class and see what your results are.
OO performance depends significantly on the MATLAB version used. I cannot comment on all versions, but know from experience that 2012a is much improved over 2010 versions. No benchmarks and so no numbers to present. My code, exclusively written using handle classes and written under 2012a will not run at all under earlier versions.
Actually no problem with your code but it is a problem with Matlab. I think in it is a kind of playing around to look like. It is nothing than overhead to compile the class code. I have done the test with simple class point (once as handle) and the other (once as value class)
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
here is the test
%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
The results t1 =
12.0212 % Handle
t2 =
12.0042 % value
t3 =
0.5489 % vector
t4 =
0.0707 % structure
Therefore for efficient performance avoid using OOP instead structure is good choice to group variables
참고URL : https://stackoverflow.com/questions/1693429/is-matlab-oop-slow-or-am-i-doing-something-wrong
'IT' 카테고리의 다른 글
업로드 된 이미지, SQL 데이터베이스 또는 디스크 파일 시스템을 저장하기에 가장 좋은 장소는 무엇입니까? (0) | 2020.06.28 |
---|---|
바이트 슬라이스를 io.Reader로 변환 (0) | 2020.06.28 |
Google 순간 검색은 어떻게 작동하나요? (0) | 2020.06.28 |
루아에는 왜“계속”진술이 없습니까? (0) | 2020.06.28 |
람다에서 캡처 이동 (0) | 2020.06.28 |