मैं कुछ समय के लिए OO MATLAB के साथ काम कर रहा हूं, और इसी तरह के प्रदर्शन के मुद्दों को देख रहा हूं।
संक्षिप्त उत्तर है: हां, MATLAB का OOP धीमा है। वहाँ पर्याप्त विधि कॉल उपरि है, मुख्यधारा OO भाषाओं की तुलना में अधिक है, और इसके बारे में आप बहुत कुछ नहीं कर सकते हैं। कारण का हिस्सा यह हो सकता है कि मुहावरेदार MATLAB विधि कॉल की संख्या को कम करने के लिए "वेक्टरकृत" कोड का उपयोग करता है, और प्रति-कॉल ओवरहेड एक उच्च प्राथमिकता नहीं है।
मैंने विभिन्न प्रकार के कार्यों और विधियों के रूप में "एनओपी" कार्यों को लिखकर प्रदर्शन को निर्धारित किया। यहाँ कुछ विशिष्ट परिणाम हैं।
>> call_nops
कंप्यूटर: पीसीविन रिलीज: 2009 बी
प्रत्येक फ़ंक्शन / विधि को 100000 बार कॉल करना
एनओपी () फ़ंक्शन: प्रति कॉल 0.02261 सेकंड 0.23 usec
nop1-5 () फ़ंक्शन: प्रति कॉल 0.02182 सेकंड 0.22 usec
एनओपी () सबफंक्शन: प्रति कॉल ०.०२२४४ सेकंड ०.२२ यूके
@ () [] अनाम फ़ंक्शन: प्रति कॉल ०.०46४६१ सेकंड ०.ec५ usec
एनओपी (obj) विधि: 0.24664 सेकंड 2.47 usec प्रति कॉल
nop1-5 (obj) के तरीके: 0.23469 सेकंड 2.35 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 sec 9.06 usec प्रति कॉल
classdef class.staticnop (): 1.16361 sec 11.64 usec प्रति कॉल
Java nop (): 2.43035 सेकंड 24.30 usec प्रति कॉल
Java static_nop (): 0.87682 सेकंड 8.77 usec प्रति कॉल
Java nop () Java से: 0.00014 sec 0.00 usec प्रति कॉल
MEX मेक्सनोप (): 0.11409 सेकंड 1.14 usec प्रति कॉल
सी एनओपी (): 0.00001 सेकंड 0.00 प्रति कॉल
R2008a पर R2009b के माध्यम से समान परिणाम। यह 32-बिट MATLAB पर चलने वाले Windows XP x64 पर है।
"जावा एनओपी ()" एक एम-कोड लूप के भीतर से बुलाया जाने वाला जावा विधि नहीं है, और प्रत्येक कॉल के साथ MATLAB-to-Java प्रेषण उपरि शामिल है। "जावा एनओपी () जावा से" एक ही चीज है जिसे जावा () लूप में जावा कहा जाता है और उस सीमा दंड को लागू नहीं करता है। नमक के एक दाने के साथ जावा और सी टाइमिंग लें; एक चतुर कंपाइलर कॉल को पूरी तरह से अनुकूलित कर सकता है।
पैकेज स्कूपिंग मैकेनिज्म नया है, इसे उसी समय के बारे में पेश किया जाता है जब क्लासडॉफ क्लासेस होता है। इसका व्यवहार संबंधित हो सकता है।
कुछ अस्थायी निष्कर्ष:
- कार्य की तुलना में विधियां धीमी हैं।
- पुरानी शैली के तरीकों की तुलना में नई शैली (क्लासिफ) विधियाँ धीमी हैं।
- नया
obj.nop()
सिंटैक्स सिंटैक्स की तुलना में धीमा है nop(obj)
, यहां तक कि एक क्लासडेफ ऑब्जेक्ट पर समान विधि के लिए भी। जावा ऑब्जेक्ट्स के लिए समान (नहीं दिखाया गया)। यदि आप तेजी से जाना चाहते हैं, तो कॉल करें nop(obj)
।
- विंडोज पर 64-बिट MATLAB में विधि कॉल ओवरहेड अधिक (लगभग 2x) है। (नहीं दिखाया।)
- MATLAB विधि प्रेषण कुछ अन्य भाषाओं की तुलना में धीमी है।
यह कहना कि ऐसा क्यों है मेरी ओर से सिर्फ अटकलबाजी होगी। MATLAB इंजन का OO इंटर्नल सार्वजनिक नहीं है। यह प्रति से अधिक बनाम संकलित मुद्दे की व्याख्या नहीं है - MATLAB में एक JIT है - लेकिन MATLAB के शिथिल टाइपिंग और वाक्यविन्यास का मतलब रन टाइम में अधिक काम हो सकता है। (जैसे आप सिंटैक्स से अकेले नहीं बता सकते हैं कि "f (x)" एक फ़ंक्शन कॉल है या किसी ऐरे में इंडेक्स है; यह रन टाइम पर कार्यक्षेत्र की स्थिति पर निर्भर करता है।) ऐसा इसलिए हो सकता है क्योंकि MATLAB की कक्षा की परिभाषाएँ बंधी हुई हैं। फाइल सिस्टम इस तरह से है कि कई अन्य भाषाएं नहीं हैं।
इसलिए क्या करना है?
एक मुहावरेदार MATLAB दृष्टिकोण यह है कि अपनी कक्षा की परिभाषाओं को संरचित करके अपने कोड को "वेक्टराइज़" करें जैसे कि एक वस्तु उदाहरण एक सरणी को लपेटता है; अर्थात्, इसके प्रत्येक क्षेत्र समानांतर सरणियाँ (जिन्हें MATLAB प्रलेखन में "प्लानर" संगठन कहा जाता है) रखती है। ऑब्जेक्ट्स की एक सरणी होने के बजाय, स्केलर मान रखने वाले फ़ील्ड्स में से प्रत्येक, उन ऑब्जेक्ट्स को परिभाषित करता है, जो स्वयं सरणियाँ हैं, और इनपुट के रूप में एरेज़ लेते हैं, और फ़ील्ड्स और इनपुट्स पर वेक्टर कॉल करते हैं। इससे की गई विधि कॉल की संख्या कम हो जाती है, उम्मीद है कि पर्याप्त प्रेषण ओवरहेड एक अड़चन नहीं है।
MATLAB में C ++ या Java क्लास की नकल करना शायद इष्टतम नहीं होगा। Java / C ++ क्लासेस आमतौर पर ऐसे बनाए जाते हैं कि ऑब्जेक्ट सबसे छोटे बिल्डिंग ब्लॉक्स होते हैं, जितने विशिष्ट हो सकते हैं (यानी, विभिन्न वर्ग के बहुत सारे), और आप उन्हें सरणियों, संग्रह ऑब्जेक्ट्स, आदि में लिखें, और छोरों के साथ उन पर पुनरावृति करें। MATLAB कक्षाएं तेज़ करने के लिए, उस दृष्टिकोण को बाहर की ओर मोड़ें। बड़े वर्ग हैं जिनके क्षेत्र सरणियाँ हैं, और उन सरणियों पर वेक्टर तरीके से कॉल करें।
बिंदु आपके कोड को भाषा की ताकत - सरणी से निपटने, वेक्टर किए गए गणित - और कमजोर स्थानों से बचने के लिए खेलने की व्यवस्था करना है।
EDIT: मूल पोस्ट के बाद से, R2010b और R2011a सामने आए हैं। समग्र चित्र वही है, जिसमें MCOS कॉल थोड़ी तेज़ हो रही हैं, और जावा और पुरानी शैली की विधि धीमी हो रही हैं ।
संपादित करें: मैं फ़ंक्शन कॉल टाइमिंग की एक अतिरिक्त तालिका के साथ "पथ संवेदनशीलता" पर यहां कुछ नोट रखता था, जहां फ़ंक्शन समय मैटलैब पथ को कैसे कॉन्फ़िगर किया गया था, से प्रभावित थे, लेकिन ऐसा लगता है कि मेरे विशेष नेटवर्क सेटअप का अपभ्रंश हो गया था समय। ऊपर दिया गया चार्ट समय के साथ मेरे परीक्षणों के पूर्वानुक्रम के समय को दर्शाता है।
अपडेट: R2011b
EDIT (2/13/2012): R2011b बाहर है, और इसे अपडेट करने के लिए प्रदर्शन चित्र काफी बदल गया है।
आर्क: पीसीविन रिलीज: 2011 बी
मशीन: R2011b, Windows XP, 8x कोर i7-2600 @ 3.40GHz, 3 GB RAM, NVIDIA NVS 300
प्रत्येक ऑपरेशन को 100000 बार करना
प्रति कॉल शैली कुल योग
एनओपी () फ़ंक्शन: 0.01578 0.16
एनओपी (), 10x लूप अनरोल: 0.01477 0.15
एनओपी (), 100x लूप अनरोल: 0.01518 0.15
nop () सबफंक्शन: 0.01559 0.16
@ () [] अनाम फ़ंक्शन: ०.०६४०० ०.६४
nop (obj) विधि: 0.28482 2.85
एनओपी () निजी समारोह: 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
क्लासडैफ स्थिरांक: 1.51890 15.19
गुणांक गुण: 0.12992 1.30
गेट्टर के साथ गुणक गुण: 1.39912 13.99
+ pkg.nop () फ़ंक्शन: 0.87345 8.73
+ pkg.nop () अंदर से + pkg: 0.80501 8.05
जावा obj.nop (): 1.86378 18.64
जावा एनओपी (obj): 0.22645 2.26
जावा फेवल ('एनओपी', ओब्ज): 0.52544 5.25
Java Klass.static_nop (): 0.35357 3.54
Java obj.nop () Java से: 0.00010 0.00
MEX मेक्सनोप (): 0.08709 0.87
सी एनओपी (): 0.00001 0.00
j () (बिलिन): 0.00251 0.03
मुझे लगता है कि इसका मुख्य कारण यह है:
- MCOS / classdef विधियां तेज हैं। लागत अब पुरानी शैली की कक्षाओं के बराबर है, जब तक आप
foo(obj)
वाक्यविन्यास का उपयोग नहीं करते हैं। इसलिए विधि की गति अब ज्यादातर मामलों में पुरानी शैली की कक्षाओं के साथ रहने का एक कारण नहीं है। (कुडोस, मैथवर्क्स!)
- नेमस्पेस में कार्य करना उन्हें धीमा कर देता है। (R2011b में नया नहीं है, मेरे परीक्षण में नया है।)
अपडेट: R2014a
मैंने बेंचमार्किंग कोड को फिर से संगठित किया है और इसे R2014a पर चलाया है।
PCWIN64 पर मतलाब R2014a
PCWIN64 विंडोज 7 6.1 (eilonwy-win7) पर मटलब 8.3.0.532 (R2014a) / जावा 1.7.0_11
मशीन: कोर i7-3615QM CPU @ 2.30GHz, 4 GB RAM (VMware वर्चुअल प्लेटफॉर्म)
nIters = 100000
ऑपरेशन का समय ()sec)
nop () फ़ंक्शन: 0.14
nop () सबफंक्शन: 0.14
@ () [] अनाम फ़ंक्शन: ०.६ ९
nop (obj) विधि: 3.28
nop () @ fcass पर निजी fcn: 0.14
classdef nop (obj): 5.30
classdef obj.nop (): 10.78
classdef pize_nop (obj): 4.88
classdef class.static_nop (): 11.81
क्लासडैफ स्थिरांक: 4.18
गुणांक गुण: 1.18
गुणक के साथ गुणक गुण: 19.26
+ pkg.nop () फ़ंक्शन: 4.03
+ pkg.nop () अंदर से + pkg: 4.16
feval ('nop'): 2.31
feval (@nop): 0.22
eval ('nop'): 59.46
जावा obj.nop (): 26.07
जावा एनओपी (obj): 3.72
जावा फेवल ('एनओपी', ओब्ज): 9.25
Java Klass.staticNop (): 10.54
जावा से जावा obj.nop (): 0.01
MEX मेक्सनोप (): 0.91
बिल्टिन j (): 0.02
संरचना s.foo क्षेत्र का उपयोग: 0.14
isempty (लगातार): 0.00
अपडेट: R2015b: ऑब्जेक्ट्स तेज़ हो गए!
यहाँ R2015b परिणाम है, कृपया @Shaked द्वारा प्रदान किया गया है। यह एक बड़ा बदलाव है: OOP काफी तेज है, और अब obj.method()
सिंटैक्स भी उतनी method(obj)
ही तेजी से है, और विरासत OOP ऑब्जेक्ट्स की तुलना में बहुत तेज है।
PCWIN64 पर Matlab R2015b
Matlab 8.6.0.267246 (R2015b) / जावा 1.7.0_60 PCWIN64 पर विंडोज 8 6.2 (नैन-शेक)
मशीन: कोर i7-4720HQ CPU @ 2.60GHz, 16 GB RAM (20378)
nIters = 100000
ऑपरेशन का समय ()sec)
nop () फ़ंक्शन: 0.04
nop () सबफंक्शन: 0.08
@ () [] अनाम फ़ंक्शन: १. .३
nop (obj) विधि: 3.15
nop () @ fcass पर निजी fcn: 0.04
classdef nop (obj): 0.28
classdef obj.nop (): 0.31
classdef pize_nop (obj): 0.34
classdef class.static_nop (): 0.05
सहपाठी स्थिर: 0.25
गुणांक गुण: 0.25
गेट्टर के साथ गुणक गुण: 0.64
+ pkg.nop () फ़ंक्शन: 0.04
+ pkg.nop () अंदर से + pkg: 0.04
feval ('nop'): 8.26
feval (@nop): 0.63
eval ('nop'): 21.22
जावा obj.nop (): 14.15
जावा एनओपी (obj): 2.50
जावा फेवल ('एनओपी', ओब्ज): 10.30
Java Klass.staticNop (): 24.48
जावा से जावा obj.nop (): 0.01
MEX मेक्सनोप (): 0.33
बिल्टिन j (): 0.15
संरचना s.foo क्षेत्र का उपयोग: 0.25
isempty (लगातार): 0.13
अपडेट: R2018a
यहाँ R2018a परिणाम है। यह बहुत बड़ी छलांग नहीं है जो हमने देखा था जब R2015b में नए निष्पादन इंजन को पेश किया गया था, लेकिन यह अभी भी वर्ष सुधार पर एक प्रशंसनीय वर्ष है। विशेष रूप से, अनाम फ़ंक्शन हैंडल को तेज़ी से रास्ता मिला।
MACI64 पर मतलाब R2018a
MACI64 Mac OS X 10.13.5 (eilonwy) पर Matlab 9.4.0.813654 (R2018a) / Java 1.8.0_144
मशीन: कोर i7-3615QM CPU @ 2.30GHz, 16 GB RAM
nIters = 100000
ऑपरेशन का समय ()sec)
nop () फ़ंक्शन: 0.03
nop () सबफंक्शन: 0.04
@ () [] अनाम फ़ंक्शन: ०.१६
classdef nop (obj): 0.16
classdef obj.nop (): 0.17
classdef pize_nop (obj): 0.16
classdef class.static_nop (): 0.03
क्लासडैफ स्थिरांक: 0.16
गुणांक गुण: 0.13
गटर के साथ गुणक गुण: 0.39
+ pkg.nop () फ़ंक्शन: 0.02
+ pkg.nop () अंदर से + pkg: 0.02
feval ('nop'): 15.62
feval (@nop): 0.43
eval ('nop'): 32.08
जावा obj.nop (): 28.77
जावा एनओपी (obj): 8.02
जावा फेवल ('एनओपी', ओब्ज): 21.85
Java Klass.staticNop (): 45.49
जावा obj.nop () जावा से: 0.03
MEX मेक्सनोप (): 3.54
बिल्टिन j (): 0.10
संरचना s.foo क्षेत्र का उपयोग: 0.16
isempty (लगातार): 0.07
अपडेट: R2018b और R2019a: कोई बदलाव नहीं
कोई महत्वपूर्ण परिवर्तन नहीं। मैं परीक्षा परिणामों को शामिल करने के लिए परेशान नहीं हूं।
बेंचमार्क के लिए सोर्स कोड
मैंने MIT लाइसेंस के तहत जारी GitHub पर इन बेंचमार्क के लिए स्रोत कोड डाल दिया है। https://github.com/apjanke/matlab-bench