Bir süredir OO MATLAB ile çalışıyorum ve benzer performans sorunlarına baktım.
Kısa cevap: evet, MATLAB'ın OOP'si biraz yavaş. Ana akım OO dillerinden daha yüksek, önemli bir yöntem çağrısı vardır ve bu konuda yapabileceğiniz çok şey yoktur. Bunun nedeni, deyimsel MATLAB'ın yöntem çağrılarının sayısını azaltmak için "vectorized" kodunu kullanması ve çağrı başına ek yükün yüksek bir öncelik olmaması olabilir.
Çeşitli işlevler ve yöntemler olarak "hiçbir şey" nop "işlevleri yazarak performansı karşılaştırdım. İşte bazı tipik sonuçlar.
>> call_nops
Bilgisayar: PCWIN Sürüm: 2009b
Her işlevin / yöntemin 100000 kez çağrılması
nop () işlevi: arama başına 0,02261 sn 0,23 usec
nop1-5 () fonksiyonları: arama başına 0,02182 sn 0,22 usec
nop () alt fonksiyonu: arama başına 0,02244 sn 0,22 usec
@ () [] anonim işlev: arama başına 0,08461 sn 0,85 usec
nop (obj) yöntemi: arama başına 0,24664 sn 2,47 usec
nop1-5 (obj) yöntemleri: arama başına 0,23469 sn 2,35 usec
nop () özel işlevi: arama başına 0,02197 sn 0,22 usec
classdef nop (obj): Çağrı başına 0.90547 sn 9.05 usec
classdef obj.nop (): arama başına 1.75522 sn 17,55 usec
classdef private_nop (obj): arama başına 8,4738 sn 8,47 usec
classdef nop (obj) (m-dosyası): arama başına 0.90560 sn 9.06 usec
classdef class.staticnop (): arama başına 1.16361 sn 11,64 usec
Java nop (): arama başına 2.43035 sn 24.30 usec
Java static_nop (): arama başına 0,8768 sn 8,77 usec
Java'dan Java nop (): Çağrı başına 0.00014 sn 0.00 usec
MEX mexnop (): arama başına 0,11409 sn 1,14 usec
C nop (): Arama başına 0,00001 sn 0,00 usec
R2008a ile R2009b arasındaki benzer sonuçlar. Bu, 32-bit MATLAB çalıştıran Windows XP x64'te bulunmaktadır.
"Java nop ()", bir M kodu döngüsünün içinden çağrılan bir hiçbir şey yapmayan Java yöntemidir ve her çağrıda MATLAB'dan Java'ya dağıtım yükünü içerir. "Java'dan Java nop ()", Java için () döngüsünde çağrılanla aynıdır ve bu sınır cezasına neden olmaz. Java ve C zamanlamalarını bir tuz tanesi ile alın; akıllı bir derleyici çağrıları tamamen optimize edebilir.
Paket kapsam belirleme mekanizması yenidir, classdef sınıflarıyla hemen hemen aynı zamanda tanıtılır. Davranışı ilişkili olabilir.
Birkaç geçici sonuç:
- Yöntemler işlevlerden daha yavaştır.
- Yeni stil (classdef) yöntemleri eski stil yöntemlerinden daha yavaştır.
- Yeni
obj.nop()
sözdizimi, nop(obj)
classdef nesnesindeki aynı yöntem için bile sözdiziminden daha yavaştır . Java nesneleri için aynıdır (gösterilmemiştir). Hızlı gitmek istiyorsanız arayın nop(obj)
.
- Windows'ta 64-bit MATLAB'da yöntem çağrısı yükü daha yüksektir (yaklaşık 2x). (Gösterilmemiş.)
- MATLAB yöntemi gönderimi diğer dillerden daha yavaştır.
Bunun neden böyle olduğunu söylemek benim açımdan spekülasyon olurdu. MATLAB motorunun OO dahili parçaları herkese açık değil. Kendi başına yorumlanmış ve derlenmiş bir sorun değildir - MATLAB bir JIT'e sahiptir - ancak MATLAB'ın daha gevşek yazması ve sözdizimi çalışma zamanında daha fazla çalışma anlamına gelebilir. (Örneğin, "f (x)" ifadesinin bir diziye bir işlev çağrısı veya dizin olup olmadığını tek başına sözdiziminden anlatamazsınız; çalışma zamanında çalışma alanının durumuna bağlıdır.) Bunun nedeni MATLAB'ın sınıf tanımlarının bağlı olması olabilir. diğer birçok dilde olmayacak şekilde dosya sistemi durumuna.
Peki ne yapmalı?
Bunun deyimsel bir MATLAB yaklaşımı, sınıf tanımlarınızı bir nesne örneği bir diziyi tamamlayacak şekilde yapılandırarak kodunuzu "vektörleştirmektir"; yani, alanlarının her biri paralel dizilere sahiptir (MATLAB belgelerinde "düzlemsel" organizasyon olarak adlandırılır). Her biri skaler değerleri tutan alanları olan bir nesne dizisine sahip olmak yerine, kendileri dizili olan nesneleri tanımlar ve yöntemlerin dizileri girdi olarak almasını sağlar ve alanlar ve girdiler üzerinde vectorized çağrılar yapar. Bu, umarım gönderme yükünün bir darboğaz olmaması için yeterli olan yöntem çağrısı sayısını azaltır.
MATLAB'da bir C ++ veya Java sınıfını taklit etmek muhtemelen uygun olmayacaktır. Java / C ++ sınıfları genellikle nesnelerin olabildiğince küçük (yani birçok farklı sınıf) yapı taşları olacak ve dizilerde, toplama nesnelerinde vb. Oluşturulacak ve döngülerle yinelenecek şekilde oluşturulur. Hızlı MATLAB sınıfları yapmak için bu yaklaşımı ters yüz edin. Alanları diziler olan daha büyük sınıflara sahip olun ve bu dizilerde vectorized yöntemler çağırın.
Mesele, kodunuzu dilin güçlü yönlerine (dizi işleme, vektörize matematik) oynamak ve zayıf noktaları önlemek için düzenlemektir.
EDIT: Orijinal gönderiden bu yana, R2010b ve R2011a çıktı. Genel resim aynıdır, MCOS çağrıları biraz daha hızlı olur ve Java ve eski stil yöntemi çağrıları yavaşlar .
DÜZENLEME: Burada "Yol hassasiyeti" ile ilgili bazı notlar vardı, burada ek işlev çağrısı zamanlamaları tablosu, fonksiyon zamanlarının Matlab yolunun nasıl yapılandırıldığından etkilendi, ancak bu benim özel ağ kurulumumda bir sapma gibi görünüyor zaman. Yukarıdaki grafik, testlerimin zaman içindeki baskınlığının tipik zamanlarını yansıtır.
Güncelleme: R2011b
EDIT (2/13/2012): R2011b çıktı ve performans resmi bunu güncelleyecek kadar değişti.
Arch: PCWIN Sürümü: 2011b
Makine: R2011b, Windows XP, 8x Core i7-2600 @ 3.40GHz, 3 GB RAM, NVIDIA NVS 300
Her işlemi 100000 kez yapmak
çağrı başına toplam µsec stili
nop () işlevi: 0.01578 0.16
nop (), 10x döngü açma: 0,01477 0,15
nop (), 100x döngü açma: 0,01518 0,15
nop () alt fonksiyonu: 0.01559 0.16
@ () [] anonim işlev: 0.06400 0.64
nop (obj) yöntemi: 0.28482 2.85
nop () özel işlevi: 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 sabiti: 1.51890 15.19
classdef özelliği: 0.12992 1.30
alıcı ile classdef özelliği: 1.39912 13.99
+ pkg.nop () işlevi: 0.87345 8.73
+ pkg.nop () içeriden + 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'dan Java obj.nop (): 0.00010 0.00
MEX mexnop (): 0,08709 0,87
C nop (): 0.00001 0.00
j () (yerleşik): 0.00251 0.03
Bence bunun sonucu şu:
- MCOS / classdef yöntemleri daha hızlıdır.
foo(obj)
Sözdizimini kullandığınız sürece maliyet artık eski stil sınıflarıyla aynı düzeydedir. Bu nedenle, yöntem hızı artık çoğu durumda eski stil sınıflarına bağlı kalmak için bir neden değildir. (Kudos, MathWorks!)
- İşlevleri ad alanlarına yerleştirmek onları yavaşlatır. (R2011b'de yeni değil, sadece testimde yeni.)
Güncelleme: R2014a
Kıyaslama kodunu yeniden oluşturdum ve R2014a'da çalıştırdım.
PCWIN64 üzerinde Matlab R2014a
Matlab 8.3.0.532 (R2014a) / PCWIN64 Windows 7 6.1 üzerinde Java 1.7.0_11 (eilonwy-win7)
Makine: Core i7-3615QM CPU @ 2.30GHz, 4 GB RAM (VMware Sanal Platformu)
Sular = 100000
Çalışma Süresi (µsn)
nop () işlevi: 0.14
nop () alt işlevi: 0.14
@ () [] anonim işlev: 0.69
nop (obj) yöntemi: 3.28
nop () özel 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 sabiti: 4.18
classdef özelliği: 1.18
alıcı ile classdef özelliği: 19.26
+ pkg.nop () işlevi: 4.03
+ pkg.nop () içeriden + 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'dan Java obj.nop (): 0.01
MEX mexnop (): 0,91
yerleşik j (): 0,02
struct s.foo sahaya erişim: 0.14
isempty (kalıcı): 0.00
Güncelleme: R2015b: Nesneler hızlandı!
@Shaked tarafından sağlanan R2015b sonuçları. Bu büyük bir değişiklik: OOP önemli ölçüde daha hızlı ve şimdi obj.method()
sözdizimi method(obj)
eski OOP nesnelerinden daha hızlı ve çok daha hızlı.
PCWIN64 üzerinde Matlab R2015b
Matlab 8.6.0.267246 (R2015b) / PCWIN64 Windows 8 6.2 üzerinde Java 1.7.0_60 (nanit sallanmış)
Makine: Core i7-4720HQ CPU @ 2.60GHz, 16 GB RAM (20378)
Sular = 100000
Çalışma Süresi (µsn)
nop () işlevi: 0.04
nop () alt işlevi: 0,08
@ () [] anonim işlev: 1.83
nop (obj) yöntemi: 3.15
nop () özel 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 sabiti: 0.25
classdef özelliği: 0.25
alıcı ile classdef özelliği: 0.64
+ pkg.nop () işlevi: 0.04
+ pkg.nop () içeriden + 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'dan Java obj.nop (): 0.01
MEX mexnop (): 0,33
yerleşik j (): 0.15
struct s.foo sahaya erişim: 0.25
isempty (kalıcı): 0.13
Güncelleme: R2018a
İşte R2018a sonuçları. Yeni yürütme motoru R2015b'de piyasaya sürüldüğünde gördüğümüz büyük sıçrama değil, ancak yine de yıldan yıla kayda değer bir gelişme. Özellikle, anonim işlev tutamaçları çok daha hızlı hale geldi.
MACI64 üzerinde Matlab R2018a
MacI64 Mac OS X 10.13.5 (eilonwy) üzerinde Matlab 9.4.0.813654 (R2018a) / Java 1.8.0_144
Makine: Core i7-3615QM CPU @ 2.30GHz, 16 GB RAM
Sular = 100000
Çalışma Süresi (µsn)
nop () işlevi: 0.03
nop () alt işlevi: 0,04
@ () [] anonim işlev: 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 sabiti: 0.16
classdef özelliği: 0.13
alıcı ile classdef özelliği: 0.39
+ pkg.nop () işlevi: 0,02
+ pkg.nop () içeriden + 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'dan Java obj.nop (): 0.03
MEX mexnop (): 3,54
yerleşik j (): 0.10
struct s.foo sahaya erişim: 0.16
isempty (kalıcı): 0,07
Güncelleme: R2018b ve R2019a: Değişiklik yok
Önemli değişiklik yok. Test sonuçlarını eklemek için uğraşmıyorum.
Deneyler için Kaynak Kodu
Bu kriterler için kaynak kodunu MIT Lisansı altında yayınlanan GitHub'a yerleştirdim. https://github.com/apjanke/matlab-bench