5

एक मैट्रिक्स A देखते हुए, मैं अन्य n वैक्टर Bi (अर्थात i=1...n) के साथ गुणा करने की आवश्यकता। A का आकार 5000x5000 जैसा हो सकता है और इस प्रकार Bi5000x1 जैसा हो सकता है।मैटलैब दोहराया आव्यूह गुणन - पाश बनाम निर्मित प्रदर्शन

अगर मैं निम्नलिखित तरीके से उत्पाद का मूल्यांकन: (परिमाण)

for i=1:n 
    product=A*Bi; 
    % do something with product 
end 

परिणाम तरीका है जैसे उत्पादों कंप्यूटिंग की तुलना में धीमी:

%assume that S is a matrix that contains the vectors Bi as columns, i.e. S(:,i)=Bi, then: 
results=A*S; %stores all the products in matrix form 
% do something with results 
समस्या

कि संख्या है n वेक्टर Bi स्मृति में संग्रहीत करने के लिए बहुत बड़ा हो सकता है, उदाहरण के लिए n=300000, इसलिए मुझे एक लूप दृष्टिकोण का उपयोग करने की आवश्यकता है जहां हर बार जब मैं उत्पाद का मूल्यांकन करता हूं, इसका उपयोग करता हूं और फिर वेक्टर Bi को त्याग देता हूं।

प्रत्यक्ष गुणा की तुलना में ऐसा दृष्टिकोण इतना धीमा क्यों है, और इस पर काबू पाने के तरीके हैं?

+3

इस शीर्ष पर अच्छी तरह से पढ़ें आईसी है [मैट्रिक्स मैट्रिक्स गुणा में इतना तेज़ क्यों है?] (http://stackoverflow.com/questions/6058139/why-is-matlab-so-fast-in-matrix-multiplication) – Adriaan

+0

गंभीरता से, गणित को उचित करना चाहिए इस पर बेंचमार्क और इसे कहीं बड़े नीयन हरे अक्षरों में प्रिंट करें। इस सवाल से कई बार पूछा गया है और अभी भी पूछा जा रहा है। जाहिर है कि वेब पर उत्तर कुछ लोगों के लिए पर्याप्त नहीं हैं, तो गणित क्यों नहीं करता है (स्रोत में बेहतर अंतर्दृष्टि के साथ) ऐसा करने का प्रयास करें? @xarz पूछने के लिए कोई पन नहीं। यदि वेब पर उत्तर संतुष्ट नहीं होते हैं, तो जाहिर है कि सवाल का कोई पर्याप्त जवाब नहीं है। – patrik

+0

@patrik शायद आप सही हैं, लेकिन मैंने स्टैक ओवरफ्लो पर देखा और मुझे इस सटीक समस्या से निपटने वाला कोई विषय नहीं मिला। वैसे, यदि आप यहां कुछ संदर्भों को लिंक कर सकते हैं जो इस सटीक समस्या से निपटते हैं तो वे भविष्य के पाठकों के लिए उपयोगी हो सकते हैं। धन्यवाद। – xanz

उत्तर

4

तुम इतनी उदाहरण

के लिए
for i = 0:(n/k)-1 
    product = A*S(:,(i*k+1):(i+1)*k) 
end 

बैचों से अधिक पाश की कोशिश और k समायोजित आप के लिए गति और स्मृति के बंद सबसे अच्छा व्यापार को खोजने के लिए कर सकते हैं।

MATLAB के लूप धीमे हैं क्योंकि यह एक व्याख्या की गई भाषा है। तो इसे फ्लाई पर बहुत सी चीजें काम करना है। जेआईटी कंपाइलर की वजह से इन दिनों लूपों में काफी सुधार हुआ है, लेकिन वे अभी भी अंतर्निहित कार्यों की तुलना में धीमे हैं जो सी में लिखे और संकलित किए गए हैं। इसके अलावा, वे वास्तव में बढ़ते सुपर फास्ट मैट्रिक्स गुणा एल्गोरिदम का उपयोग करते हैं, जैसा कि तुलना में लूपिंग द्वारा प्राप्त आपके निष्पक्ष निष्पक्ष एल्गोरिदम के साथ, जो आप जिस गति-गति का अनुभव कर रहे हैं उसमें भी सहायता करते हैं।

+1

आप 'parfor' का उपयोग करके, इस मामले में समानांतर भी जा सकते हैं। गणनाओं के पर्याप्त कोर और जटिलता (या आकार) को देखते हुए जो एक महत्वपूर्ण गति वृद्धि हो सकती है। – Adriaan

+1

@Adriaan शायद इसे एक और जवाब के रूप में जोड़ने लायक है। हालांकि अगर मुझे गलत नहीं लगता है, तो '*' ऑपरेटर पहले से ही समानांतर है, इसलिए भविष्यवाणी करना मुश्किल है कि किस तरह की गति की उम्मीद है और यह स्मृति की बाधाओं में भी मदद नहीं करेगा। – Dan

+1

स्लाइसिंग में एक बग है, यह के साथ शुरू होता है और इसमें प्रत्येक के-वें तत्व दो बार होता है। – Daniel

3

सादगी के लिए मेरा उत्तर एन-बाय-एन स्क्वायर मैट्रिक्स ए मान लेगा, लेकिन यह गैर वर्गों के लिए भी सच है।

आपका लूप दृष्टिकोण मैट्रिक्स वेक्टर गुणा का उपयोग करता है। बेवकूफ समाधान भी सबसे अच्छा ज्ञात है, जिसके परिणामस्वरूप ओ (एन^2) का रनटाइम होता है जिसे बार बार दोहराया जाता है। आप ओ (एन^3) के कुल रनटाइम के साथ समाप्त होते हैं।

मैट्रिक्स गुणा के लिए, एक बेहतर दृष्टिकोण है। सबसे अच्छी तरह से ज्ञात एल्गोरिदम केवल ओ (एन^2.4) रनटाइम से कम की आवश्यकता है, जो इसे बड़ी संख्या के लिए बहुत तेज बनाता है।

मैट्रिक्स गुणा का उपयोग करते हुए एक बार कई वैक्टरों को गुणा करते समय आप बेहतर रनटाइम प्राप्त करेंगे। यह शुद्ध मैट्रिक्स गुणा के प्रदर्शन को प्राप्त नहीं करेगा, लेकिन बी के बड़े स्लाइस के साथ काम करना शायद सबसे तेज़ स्मृति कुशल समाधान है।

अलग चर्चा की दृष्टिकोण के लिए कुछ कोड:

n=5000; 
k=100; 
A=rand(n,n); 
S=rand(n,n); 
workers=matlabpool('size'); 
%for a parfor solution, the batch size must be smaller because multiple batches are stred in memory at once 
kparallel=k/workers; 
disp('simple loop:'); 
tic; 
for i = 1:n 
    product = A*S(:,n); 
end 
toc 
disp('batched loop:'); 
tic; 
for i = 1:(n/k) 
    product = A*S(:,(i-1)*k+1:(i)*k); 
end 
toc 
disp('batched parfor loop:'); 
tic; 
parfor i = 1:(n/kparallel) 
    product = A*S(:,(i-1)*kparallel+1:(i)*kparallel); 
end 
toc 
disp('matrix multiplication:'); 
tic; 
A*S; 
toc 
+0

धन्यवाद, इन एल्गोरिदम के रनटाइम पर बहुत ही रोचक टिप्पणी, यह समस्या बताती है कि – xanz

+1

'मैटलबूल ('आकार')' अब R2015a में काम नहीं कर रहा है, आपको 'parfor' – Adriaan

1

@Dan's answer के अलावा आप समानांतर जा रहा कोशिश कर सकते हैं में, बशर्ते आप पर्याप्त कोर और बड़ा पर्याप्त संचालन सुनिश्चित करने के लिए यह लाभदायक (स्मृति के बारे में अधिक जानकारी के लिए this answer देखना है parfor की खपत):

parfor ii = 0:(n/k)-1 
    product = A*S(:,(ii*k+1):(ii+1)*k) 
end 

मैं docs on mtimes (* ऑपरेटर में नहीं देख सकते हैं) है कि क्या यह परोक्ष थ्रेड है, लेकिन यह है मुझे लगता है कि एक शॉट के लायक है।

+2

का उपयोग करना होगा 'parfor' का उपयोग करने के बजाय, मैं स्मृति बैच तक पहुंचने तक बड़े बैच आकारों का उपयोग करने की अनुशंसा करता हूं। वह तेज़ होगा। – Daniel

+0

मैंने पहले से ही parfor कोशिश की है, यह मदद करता है लेकिन दुर्भाग्य से इतना नहीं ... – xanz

+0

@xarz तो डैनियल ने वास्तव में क्या कहा है; मैट्रिक्स गुणा इतना तेज है कि समानांतर जाने की तुलना में जितना संभव हो उतना बड़ा बैचों में प्रक्रिया करना बेहतर होता है। – Adriaan

0

मैट्रिक्स के साथ प्रत्येक सरणी के गुणों को करने के लिए बस मैट्रिक्स को एक मैट्रिक्स के साथ गुणा करें जो स्तंभों के रूप में आपके इच्छित सरणी होंगे।

तो आप जाँच करना चाहते हैं तो इस

अगर

size(a)=3,3 

तो

a*b==horzcat(a*b(:,1),a*b(:,2),a*b(:,3)) 

आप पाश

से बहुत समय बचाने के सच

इस तरह है

संबंधित मुद्दे