इस उत्तर के निचले भाग में कुछ बेंचमार्किंग कोड है, क्योंकि आपने स्पष्ट किया है कि आप for
लूप से बचने के बजाय प्रदर्शन में रुचि रखते हैं ।
वास्तव में, मुझे लगता है कि for
लूप शायद यहां का सबसे अच्छा विकल्प है। चूंकि "नया" (2015 बी) जेआईटी इंजन पेश किया गया था ( स्रोत ) for
लूप स्वाभाविक रूप से धीमा नहीं हैं - वास्तव में वे आंतरिक रूप से अनुकूलित हैं।
आप बेंचमार्क से देख सकते हैं कि mat2cell
थॉमसआईसकोडिंग द्वारा यहां दिया गया विकल्प बहुत धीमा है ...
यदि हम स्केल को स्पष्ट करने के लिए उस रेखा से छुटकारा पा लेते हैं, तो मेरा splitapply
तरीका काफी धीमा है, ऑबकार्डन का एक्सीमरेयर विकल्प थोड़ा बेहतर है, लेकिन सबसे तेज़ (और तुलनीय) विकल्प या तो उपयोग कर रहे हैं arrayfun
(जैसा कि थॉमस द्वारा भी सुझाव दिया गया है) या एक for
लूप। ध्यान दें कि arrayfun
मूल for
रूप से अधिकांश उपयोग-मामलों के लिए भेस में एक लूप है, इसलिए यह एक आश्चर्यजनक टाई नहीं है!
मैं आपको for
कोड की पठनीयता और सर्वश्रेष्ठ प्रदर्शन के लिए एक लूप का उपयोग करने की सलाह दूंगा।
संपादित करें :
यदि हम मानते हैं कि लूपिंग सबसे तेज़ दृष्टिकोण है, तो हम find
कमांड के चारों ओर कुछ अनुकूलन कर सकते हैं ।
विशेष रूप से
M
तार्किक बनाओ । जैसा कि नीचे दिए गए कथानक से पता चलता है, यह अपेक्षाकृत छोटे के लिए तेज़ हो सकता है M
, लेकिन बड़े के लिए प्रकार रूपांतरण के व्यापार-बंद के साथ धीमा M
।
उपयोग M
करने के 1:size(M,2)
बजाय किसी सरणी को अनुक्रमित करने के लिए तार्किक का उपयोग करें find
। यह लूप ( find
कमांड) के सबसे धीमे हिस्से से बचा जाता है और ओवरहेड प्रकार को ओवरहेड करता है, जिससे यह सबसे तेज विकल्प बन जाता है।
यहाँ सर्वश्रेष्ठ प्रदर्शन के लिए मेरी सिफारिश है:
function A = f_forlooplogicalindexing( M )
M = logical(M);
k = 1:size(M,2);
N = size(M,1);
A = cell(N,1);
for r = 1:N
A{r} = k(M(r,:));
end
end
मैंने इसे नीचे दिए गए मानदंड में जोड़ा है, यहाँ लूप-शैली के दृष्टिकोण की तुलना है:
बेंचमार्किंग कोड:
rng(904); % Gives OP example for randi([0,1],3)
p = 2:12;
T = NaN( numel(p), 7 );
for ii = p
N = 2^ii;
M = randi([0,1],N);
fprintf( 'N = 2^%.0f = %.0f\n', log2(N), N );
f1 = @()f_arrayfun( M );
f2 = @()f_mat2cell( M );
f3 = @()f_accumarray( M );
f4 = @()f_splitapply( M );
f5 = @()f_forloop( M );
f6 = @()f_forlooplogical( M );
f7 = @()f_forlooplogicalindexing( M );
T(ii, 1) = timeit( f1 );
T(ii, 2) = timeit( f2 );
T(ii, 3) = timeit( f3 );
T(ii, 4) = timeit( f4 );
T(ii, 5) = timeit( f5 );
T(ii, 6) = timeit( f6 );
T(ii, 7) = timeit( f7 );
end
plot( (2.^p).', T(2:end,:) );
legend( {'arrayfun','mat2cell','accumarray','splitapply','for loop',...
'for loop logical', 'for loop logical + indexing'} );
grid on;
xlabel( 'N, where M = random N*N matrix of 1 or 0' );
ylabel( 'Execution time (s)' );
disp( 'Done' );
function A = f_arrayfun( M )
A = arrayfun(@(r) find(M(r,:)),1:size(M,1),'UniformOutput',false);
end
function A = f_mat2cell( M )
[i,j] = find(M.');
A = mat2cell(i,arrayfun(@(r) sum(j==r),min(j):max(j)));
end
function A = f_accumarray( M )
[val,ind] = ind2sub(size(M),find(M.'));
A = accumarray(ind,val,[],@(x) {x});
end
function A = f_splitapply( M )
[r,c] = find(M);
A = splitapply( @(x) {x}, c, r );
end
function A = f_forloop( M )
N = size(M,1);
A = cell(N,1);
for r = 1:N
A{r} = find(M(r,:));
end
end
function A = f_forlooplogical( M )
M = logical(M);
N = size(M,1);
A = cell(N,1);
for r = 1:N
A{r} = find(M(r,:));
end
end
function A = f_forlooplogicalindexing( M )
M = logical(M);
k = 1:size(M,2);
N = size(M,1);
A = cell(N,1);
for r = 1:N
A{r} = k(M(r,:));
end
end
for
लूप से बचें ? इस समस्या के लिए, MATLAB के आधुनिक संस्करणों के साथ, मुझेfor
सबसे तेज़ समाधान होने का संदेह है । यदि आपको कोई प्रदर्शन समस्या है, तो मुझे संदेह है कि आप पुरानी सलाह के आधार पर समाधान के लिए गलत जगह देख रहे हैं।