MATLAB Language
प्रदर्शन और बेंचमार्किंग
खोज…
टिप्पणियों
- कोडिंग " प्रीमैच्योर ऑप्टिमाइज़ेशन " के खतरनाक अभ्यास से बचने का एक तरीका है, डेवलपर को कोड के उन हिस्सों पर ध्यान केंद्रित करके, जो वास्तव में अनुकूलन प्रयासों को सही ठहराते हैं।
- MATLAB प्रलेखन लेख " आपके कार्यक्रम के प्रदर्शन को मापें " शीर्षक।
Profiler का उपयोग करके प्रदर्शन की अड़चन की पहचान करना
MATLAB प्रोफाइलर के लिए एक उपकरण है सॉफ्टवेयर रूपरेखा MATLAB कोड की। Profiler का उपयोग करना, निष्पादन समय और मेमोरी खपत दोनों का दृश्य प्रतिनिधित्व प्राप्त करना संभव है।
Profiler चलाना दो तरीकों से किया जा सकता है:
MATLAB GUI में "रन एंड टाइम" बटन पर क्लिक करते हुए संपादक में कुछ
.m
फाइल खुली ( R2012b में जोड़ी गई)।प्रोग्रामेटिक रूप से, उपयोग करना:
profile on <some code we want to test> profile off
नीचे कुछ नमूना कोड और इसकी रूपरेखा का परिणाम है:
function docTest
for ind1 = 1:100
[~] = var(...
sum(...
randn(1000)));
end
spy
ऊपर से हम सीखते हैं कि spy
कार्य कुल निष्पादन समय का लगभग 25% लेता है। "वास्तविक कोड" के मामले में, एक ऐसा फ़ंक्शन जो निष्पादन के समय का इतना बड़ा प्रतिशत लेता है, अनुकूलन के लिए एक अच्छा उम्मीदवार होगा, क्योंकि var
और cla
अनुरूप कार्यों के विपरीत जिनके अनुकूलन से बचा जाना चाहिए।
इसके अलावा, फंक्शन नेम कॉलम में प्रविष्टियों पर क्लिक करना संभव है ताकि उस प्रविष्टि के लिए निष्पादन समय का एक विस्तृत ब्रेकडाउन हो सके। यहाँ spy
क्लिक करने का उदाहरण है:
प्रोफाइलर को चलाने से पहले profile('-memory')
को निष्पादित करके मेमोरी की खपत को प्रोफाइल करना भी संभव है।
कई कार्यों के निष्पादन समय की तुलना करना
tic
और toc
का व्यापक रूप से उपयोग किया जाने वाला संयोजन किसी फ़ंक्शन या कोड स्निपेट के निष्पादन समय का एक मोटा विचार प्रदान कर सकता है।
कई कार्यों की तुलना करने के लिए इसका उपयोग नहीं किया जाना चाहिए। क्यों? उपरोक्त कोड का उपयोग करके स्क्रिप्ट के भीतर तुलना करने के लिए सभी कोड स्निपेट्स के लिए समान स्थिति प्रदान करना लगभग असंभव है। हो सकता है कि फ़ंक्शन समान फ़ंक्शन स्थान और सामान्य चर साझा करते हैं, इसलिए बाद में फ़ंक्शन और कोड स्निपेट्स पहले से ही आरंभिक चर और फ़ंक्शन का लाभ उठाते हैं। इसके अलावा, इस बात की कोई जानकारी नहीं है कि क्या JIT कंपाइलर बाद में समान रूप से स्निपेट्स कहे जाने वाले इन हैंडल करेगा।
बेंचमार्क के लिए समर्पित कार्य timeit
। निम्न उदाहरण इसके उपयोग को दर्शाता है।
सरणी A
और मैट्रिक्स B
। यह निर्धारित किया जाना चाहिए कि विभिन्न तत्वों की संख्या की गणना करके B
की कौन सी पंक्ति A
समान है।
function t = bench()
A = [0 1 1 1 0 0];
B = perms(A);
% functions to compare
fcns = {
@() compare1(A,B);
@() compare2(A,B);
@() compare3(A,B);
@() compare4(A,B);
};
% timeit
t = cellfun(@timeit, fcns);
end
function Z = compare1(A,B)
Z = sum( bsxfun(@eq, A,B) , 2);
end
function Z = compare2(A,B)
Z = sum(bsxfun(@xor, A, B),2);
end
function Z = compare3(A,B)
A = logical(A);
Z = sum(B(:,~A),2) + sum(~B(:,A),2);
end
function Z = compare4(A,B)
Z = pdist2( A, B, 'hamming', 'Smallest', 1 );
end
बेंचमार्क का यह तरीका पहली बार इस जवाब में देखा गया था।
यह `सिंगल` होना ठीक है!
अवलोकन:
MATLAB में संख्यात्मक सरणियों के लिए डिफ़ॉल्ट डेटा प्रकार double
। double
का एक फ्लोटिंग पॉइंट प्रतिनिधित्व है , और यह प्रारूप प्रति मूल्य 8 बाइट्स (या 64 बिट्स) लेता है। कुछ मामलों में, जहां उदाहरण केवल पूर्णांक के साथ काम कर रहे हैं या जब संख्यात्मक अस्थिरता एक आसन्न मुद्दा नहीं है, तो ऐसी उच्च बिट गहराई की आवश्यकता नहीं हो सकती है। इस कारण से, single
परिशुद्धता (या अन्य उपयुक्त प्रकार ) के लाभों पर विचार करने की सलाह दी जाती है:
- तेज़ निष्पादन समय (विशेष रूप से GPU पर ध्यान देने योग्य)।
- मेमोरी की आधी खपत: वह सफल हो सकती है जहाँ
double
आउट ऑफ़ मेमोरी त्रुटि के कारण विफल हो जाता है; फ़ाइलों के रूप में संग्रहीत करते समय अधिक कॉम्पैक्ट।
किसी समर्थित डेटा प्रकार से single
में परिवर्तनशील का उपयोग करके किया जाता है:
sing_var = single(var);
कुछ आमतौर पर उपयोग किए जाने वाले कार्य (जैसे: zeros
, eye
, ones
, आदि ) जो डिफ़ॉल्ट रूप से double
मान का उत्पादन करते ones
, आउटपुट के प्रकार / वर्ग को निर्दिष्ट करने की अनुमति देते हैं।
स्क्रिप्ट को एक गैर-डिफ़ॉल्ट परिशुद्धता / प्रकार / वर्ग में परिवर्तित करना:
जुलाई 2016 तक, डिफ़ॉल्ट MATLAB डेटा प्रकार को double
से बदलने के लिए कोई प्रलेखित तरीका मौजूद नहीं है।
MATLAB में, नए वैरिएबल आमतौर पर बनाते समय उपयोग किए जाने वाले वैरिएबल के डेटा प्रकारों की नकल करते हैं। इसे समझने के लिए, निम्नलिखित उदाहरण पर विचार करें:
A = magic(3);
B = diag(A);
C = 20*B;
>> whos C
Name Size Bytes Class Attributes
C 3x1 24 double
A = single(magic(3)); % A is converted to "single"
B = diag(A);
C = B*double(20); % The stricter type, which in this case is "single", prevails
D = single(size(C)); % It is generally advised to cast to the desired type explicitly.
>> whos C
Name Size Bytes Class Attributes
C 3x1 12 single
इस प्रकार, कोड में परिवर्तन की अनुमति देने के लिए कई प्रारंभिक चर डालना / परिवर्तित करना पर्याप्त लग सकता है - हालाँकि यह हतोत्साहित है (नीचे दिए गए कैवेट और नुकसान देखें)।
कैविट्स और नुकसान:
संख्यात्मक शोर (जब
single
सेdouble
तक कास्टिंग) या जानकारी के नुकसान (जबdouble
सेsingle
, या कुछ पूर्णांक प्रकारों के बीच कास्टिंग) की शुरूआत के कारण बार-बार रूपांतरण हतोत्साहित किया जाता है , जैसे:double(single(1.2)) == double(1.2) ans = 0
यह
typecast
का उपयोग करके कुछ हद तक कम किया जा सकता है। फ्लोटिंग पॉइंट की अशुद्धि के बारे में भी देखें।पूरी तरह से अंतर्निहित डेटा-टाइपिंग पर निर्भर (यानी MATLAB का अनुमान है कि एक संगणना के उत्पादन का प्रकार क्या होना चाहिए) कई अवांछित प्रभावों के कारण हतोत्साहित किया जाता है:
जानकारी का नुकसान : जब एक
double
परिणाम की उम्मीद की जाती है, लेकिनsingle
औरdouble
ऑपरेंड का एक लापरवाह संयोजनsingle
परिशुद्धता प्राप्त करता है।अप्रत्याशित रूप से उच्च मेमोरी खपत : जब
single
परिणाम की उम्मीद की जाती है, लेकिन एक लापरवाह गणना एकdouble
आउटपुट में परिणाम देती है।GPU के साथ काम करते समय अनावश्यक ओवरहेड : जब गैर-
gpuArray
वैरिएबल (अर्थात आमतौर पर रैम में संग्रहीत) के साथgpuArray
प्रकार (अर्थात चर में संग्रहित) कोgpuArray
, डेटा कोgpuArray
किए जाने से पहले एक या दूसरे तरीके से स्थानांतरित करना होगा। इस ऑपरेशन में समय लगता है, और दोहराए जाने वाले संगणना में बहुत ध्यान देने योग्य हो सकता है।पूर्णांक प्रकारों के साथ फ़्लोटिंग-पॉइंट प्रकारों को मिलाते समय त्रुटियां : पूर्णांक और फ़्लोटिंग पॉइंट प्रकारों के मिश्रित इनपुट के लिए
mtimes
(*
) जैसे कार्य परिभाषित नहीं हैं - और त्रुटि होगी। पूर्णांक प्रकार के इनपुट के लिएtimes
(.*
) जैसे कार्य परिभाषित नहीं हैं - और फिर त्रुटि होगी।>> ones(3,3,'int32')*ones(3,3,'int32') Error using * MTIMES is not fully supported for integer classes. At least one input must be scalar. >> ones(3,3,'int32').*ones(3,3,'double') Error using .* Integers can only be combined with integers of the same class, or scalar doubles.
बेहतर कोड पठनीयता और अवांछित प्रकार के जोखिम को कम करने के लिए, एक रक्षात्मक दृष्टिकोण की सलाह दी जाती है , जहां चर स्पष्ट रूप से वांछित प्रकार के लिए डाले जाते हैं।
यह सभी देखें:
- MATLAB प्रलेखन: फ़्लोटिंग-पॉइंट नंबर ।
- मैथवर्क्स का तकनीकी आलेख: MATLAB कोड को फिक्स्ड प्वाइंट में परिवर्तित करने के लिए सर्वोत्तम अभ्यास ।
ND-array को पुनर्व्यवस्थित करने से समग्र प्रदर्शन में सुधार हो सकता है
कुछ मामलों में हमें एनडी-सरणियों के एक सेट पर कार्यों को लागू करने की आवश्यकता होती है। आइए इस सरल उदाहरण को देखें।
A(:,:,1) = [1 2; 4 5];
A(:,:,2) = [11 22; 44 55];
B(:,:,1) = [7 8; 1 2];
B(:,:,2) = [77 88; 11 22];
A =
ans(:,:,1) =
1 2
4 5
ans(:,:,2) =
11 22
44 55
>> B
B =
ans(:,:,1) =
7 8
1 2
ans(:,:,2) =
77 88
11 22
दोनों मैट्रीक 3 डी हैं, मान लें कि हमें निम्नलिखित गणना करनी है:
result= zeros(2,2);
...
for k = 1:2
result(i,j) = result(i,j) + abs( A(i,j,k) - B(i,j,k) );
...
if k is very large, this for-loop can be a bottleneck since MATLAB order the data in a column major fashion. So a better way to compute "result" could be:
% trying to exploit the column major ordering
Aprime = reshape(permute(A,[3,1,2]), [2,4]);
Bprime = reshape(permute(B,[3,1,2]), [2,4]);
>> Aprime
Aprime =
1 4 2 5
11 44 22 55
>> Bprime
Bprime =
7 1 8 2
77 11 88 22
अब हम निम्नलिखित के लिए उपरोक्त लूप को प्रतिस्थापित करते हैं:
result= zeros(2,2);
....
temp = abs(Aprime - Bprime);
for k = 1:2
result(i,j) = result(i,j) + temp(k, i+2*(j-1));
...
हमने डेटा को फिर से व्यवस्थित किया ताकि हम कैश मेमोरी का फायदा उठा सकें। क्रमपरिवर्तन और फेरबदल महंगा हो सकता है लेकिन बड़े एनडी-सरणियों के साथ काम करते समय इन कार्यों से संबंधित कम्प्यूटेशनल लागत व्यवस्थित एरेज के साथ काम करने की तुलना में बहुत कम है।
उपदेश का महत्व
MATLAB में Arrays को मेमोरी में निरंतर ब्लॉक के रूप में रखा जाता है, MATLAB द्वारा स्वचालित रूप से आवंटित और जारी किया जाता है। MATLAB सिंटैक्स का उपयोग करने के लिए एक सरणी का आकार बदलने के रूप में स्मृति प्रबंधन संचालन को छुपाता है:
a = 1:4
a =
1 2 3 4
a(5) = 10 % or alternatively a = [a, 10]
a =
1 2 3 4 10
यह समझना महत्वपूर्ण है कि ऊपर एक तुच्छ ऑपरेशन नहीं है, a(5) = 10
MATLAB का कारण होगा आकार 5 की स्मृति का एक नया ब्लॉक आवंटित करने के लिए, पहले 4 संख्याओं की प्रतिलिपि बनाएँ, और 5'th को 10 पर सेट करें। वह O(numel(a))
ऑपरेशन है, और O(1)
।
निम्नलिखित को धयान मे रखते हुए:
clear all
n=12345678;
a=0;
tic
for i = 2:n
a(i) = sqrt(a(i-1)) + i;
end
toc
Elapsed time is 3.004213 seconds.
इस लूप में a
वास्तविक बार n
(MATLAB द्वारा किए गए कुछ अनुकूलन को छोड़कर)! ध्यान दें कि MATLAB हमें एक चेतावनी देता है:
"चर 'ए' प्रत्येक लूप पुनरावृत्ति पर आकार बदलता प्रतीत होता है। गति के लिए प्रचार करने पर विचार करें।"
जब हम प्रचार करते हैं तो क्या होता है?
a=zeros(1,n);
tic
for i = 2:n
a(i) = sqrt(a(i-1)) + i;
end
toc
Elapsed time is 0.410531 seconds.
हम देख सकते हैं कि रनटाइम को परिमाण के एक क्रम से कम किया जाता है।
उपदेश के लिए तरीके:
MATLAB वैक्टर और मैट्रिस के आवंटन के लिए उपयोगकर्ता की विशिष्ट आवश्यकताओं के आधार पर विभिन्न कार्य प्रदान करता है। इनमें शामिल हैं: zeros
, ones
, nan
, eye
, true
आदि।
a = zeros(3) % Allocates a 3-by-3 matrix initialized to 0
a =
0 0 0
0 0 0
0 0 0
a = zeros(3, 2) % Allocates a 3-by-2 matrix initialized to 0
a =
0 0
0 0
0 0
a = ones(2, 3, 2) % Allocates a 3 dimensional array (2-by-3-by-2) initialized to 1
a(:,:,1) =
1 1 1
1 1 1
a(:,:,2) =
1 1 1
1 1 1
a = ones(1, 3) * 7 % Allocates a row vector of length 3 initialized to 7
a =
7 7 7
एक डेटा प्रकार भी निर्दिष्ट किया जा सकता है:
a = zeros(2, 1, 'uint8'); % allocates an array of type uint8
मौजूदा सरणी के आकार को क्लोन करना भी आसान है:
a = ones(3, 4); % a is a 3-by-4 matrix of 1's
b = zeros(size(a)); % b is a 3-by-4 matrix of 0's
और क्लोन प्रकार:
a = ones(3, 4, 'single'); % a is a 3-by-4 matrix of type single
b = zeros(2, 'like', a); % b is a 2-by-2 matrix of type single
ध्यान दें कि 'like' भी क्लोनिंग जटिलता और स्पार्सिटी है ।
प्रीक्लोकेशन को किसी भी फ़ंक्शन का उपयोग करके प्राप्त किया जाता है जो अंतिम आवश्यक आकार की एक सरणी देता है, जैसे कि rand
, gallery
, kron
, bsxfun
, colon
और कई अन्य। उदाहरण के लिए, रैखिक भिन्न तत्वों के साथ वैक्टर आवंटित करने का एक सामान्य तरीका कोलन ऑपरेटर (2- या 3-ऑपरेंड संस्करण 1 के साथ ) का उपयोग करके है:
a = 1:3
a =
1 2 3
a = 2:-3:-4
a =
2 -1 -4
सेल सरणियों को cell()
फ़ंक्शन का उपयोग करके उसी तरह से आवंटित किया जा सकता है जैसे कि zeros()
।
a = cell(2,3)
a =
[] [] []
[] [] []
ध्यान दें कि सेल एरे को सेल कंटेंट की याद में स्थानों पर पॉइंटर्स लगाकर काम करते हैं। इसलिए सभी उपदेश युक्तियाँ व्यक्तिगत सेल सरणी तत्वों पर भी लागू होती हैं।
आगे की पढाई:
- " प्रीलीकोलेटिंग मेमोरी " पर आधिकारिक MATLAB प्रलेखन ।
- आधिकारिक MATLAB प्रलेखन " कैसे MATLAB आवंटित करता है मेमोरी "।
- Preallocation प्रदर्शन पर Undocumented matlab ।
- MATLAB की कला पर लॉरेन पर एरे प्रेलोकेशन को समझना