5

के साथ Matlab धीमी समांतर प्रसंस्करण matlab में वितरित और कोडित वितरित सरणी का उपयोग करने के लिए मैं नया हूँ। समानांतर कोड मैंने काम किया है, लेकिन धारावाहिक संस्करण से बहुत धीमा है और मुझे नहीं पता कि क्यों। नीचे दिए गए कोड उदाहरण वॉल्यूमेटिक डेटा से हेसियन मैट्रिस के eigenvalues ​​की गणना करें।वितरित सरणी

सीरियल संस्करण:

S = size(D); 
Dsmt=imgaussian(D,2,20); 
[fx, fy, fz] = gradient(Dsmt); 
DHess = zeros([3 3 S(1) S(2) S(3)]); 
[DHess(1,1,:,:,:), DHess(1,2,:,:,:), DHess(1,3,:,:,:)] = gradient(fx); 
[DHess(2,1,:,:,:), DHess(2,2,:,:,:), DHess(2,3,:,:,:)] = gradient(fy); 
[DHess(3,1,:,:,:), DHess(3,2,:,:,:), DHess(3,3,:,:,:)] = gradient(fz); 

d = zeros([3 S(1) S(2) S(3)]); 
for i = 1 : S(1) 
    fprintf('Slice %d out of %d\n', i, S(1)); 
    for ii = 1 : S(2) 
     for iii = 1 : S(3) 
      d(:,i,ii,iii) = eig(squeeze(DHess(:,:,i,ii,iii))); 
     end 
    end 
end 

समानांतर संस्करण:

S = size(D); 
Dsmt=imgaussian(D,2,20); 
[fx, fy, fz] = gradient(Dsmt); 
DHess = zeros([3 3 S(1) S(2) S(3)]); 
[DHess(1,1,:,:,:), DHess(1,2,:,:,:), DHess(1,3,:,:,:)] = gradient(fx); 
[DHess(2,1,:,:,:), DHess(2,2,:,:,:), DHess(2,3,:,:,:)] = gradient(fy); 
[DHess(3,1,:,:,:), DHess(3,2,:,:,:), DHess(3,3,:,:,:)] = gradient(fz); 
CDHess = distributed(DHess); 
spmd 
    d = zeros([3 S(1) S(2) S(3)], codistributor('1d',4)); 
    for i = 1 : S(1) 
     fprintf('Slice %d out of %d\n', i, S(1)); 
     for ii = 1 : S(2) 
      for iii = drange(1 : S(3)) 
       d(:,i,ii,iii) = eig(squeeze(CDHess(:,:,i,ii,iii))); 
      end 
     end 
    end 
end 

किसी मुद्दे पर कुछ प्रकाश डाला सकता है मैं बहुत आभारी होंगे

+0

एक ही पुनरावृत्ति कितनी देर तक लेता है? – Jonas

+0

क्या आप अपना मैटलबूल खोल रहे हैं? – Rasman

+0

@ जोनास धारावाहिक संस्करण पर एक एकल पुनरावृत्ति (चर परिवर्तनीय i) लगभग 1.7 सेकंड लेता है।समांतर संस्करण पर एक ही पुनरावृत्ति 5 मिनट से अधिक नहीं हो पाती है जिस बिंदु पर मैंने निष्पादन को समाप्त कर दिया है। – Hampycalc

उत्तर

2

यहां आपके कोड का एक पुनः लिखा गया संस्करण है। मैंने बाहरी-अधिकांश लूप पर काम को विभाजित कर दिया है, न कि आपके मामले में - आंतरिक-अधिकांश लूप। मैंने स्पष्ट रूप से d परिणाम वेक्टर के स्थानीय हिस्सों और हेसियन मैट्रिक्स के स्थानीय हिस्से को भी आवंटित किया है।

अपने कोड में आप काम को विभाजित करने के लिए drange पर भरोसा करते हैं, और आप स्थानीय हिस्से को निकालने से बचने के लिए सीधे वितरित सरणी तक पहुंचते हैं। माना जाता है कि अगर MATLAB ने सबकुछ ठीक से किया तो इसका परिणाम इतनी बड़ी मंदी नहीं होनी चाहिए। निचली पंक्ति यह है कि, मुझे नहीं पता कि आपका कोड इतना धीमा क्यों है - सबसे अधिक संभावना है क्योंकि MATLAB आपके मैट्रिक्स को वितरित करने के तथ्य के बावजूद कुछ दूरस्थ डेटा एक्सेस कर रहा है।

वैसे भी, नीचे दिया गया कोड चलता है और 4 प्रयोगशालाओं का उपयोग करके मेरे कंप्यूटर पर बहुत अच्छी गति देता है। मैंने कुछ काम करने के लिए सिंथेटिक यादृच्छिक इनपुट डेटा उत्पन्न किया है। टिप्पणियों पर एक नज़र डालें। अगर कुछ अस्पष्ट है, तो मैं बाद में विस्तार कर सकता हूं।

clear all; 

D = rand(512, 512, 3); 
S = size(D); 
[fx, fy, fz] = gradient(D); 

% this part could also be parallelized - at least a bit. 
tic; 
DHess = zeros([3 3 S(1) S(2) S(3)]); 
[DHess(1,1,:,:,:), DHess(1,2,:,:,:), DHess(1,3,:,:,:)] = gradient(fx); 
[DHess(2,1,:,:,:), DHess(2,2,:,:,:), DHess(2,3,:,:,:)] = gradient(fy); 
[DHess(3,1,:,:,:), DHess(3,2,:,:,:), DHess(3,3,:,:,:)] = gradient(fz); 
toc 

% your sequential implementation 
d = zeros([3, S(1) S(2) S(3)]); 
disp('sequential') 
tic 
for i = 1 : S(1) 
    for ii = 1 : S(2) 
     for iii = 1 : S(3) 
      d(:,i,ii,iii) = eig(squeeze(DHess(:,:,i,ii,iii))); 
     end 
    end 
end 
toc 

% my parallel implementation 
disp('parallel') 
tic 
spmd 
    % just for information 
    disp(['lab ' num2str(labindex)]); 

    % distribute the input data along the third dimension 
    % This is the dimension of the outer-most loop, hence this is where we 
    % want to parallelize! 
    DHess_dist = codistributed(DHess, codistributor1d(3)); 
    DHess_local = getLocalPart(DHess_dist); 

    % create an output data distribution - 
    % note that this time we split along the second dimension 
    codist = codistributor1d(2, codistributor1d.unsetPartition, [3, S(1) S(2) S(3)]); 
    localSize = [3 codist.Partition(labindex) S(2) S(3)]; 

    % allocate local part of the output array d 
    d_local = zeros(localSize); 

    % your ordinary loop, BUT! the outermost loop is split amongst the 
    % threads explicitly, using local indexing. In the loop only local parts 
    % of matrix d and DHess are accessed 
    for i = 1:size(d_local,2) 
     for ii = 1 : S(2) 
      for iii = 1 : S(3) 
       d_local(:,i,ii,iii) = eig(squeeze(DHess_local(:,:,i,ii,iii))); 
      end 
     end 
    end 

    % assemble local results to a codistributed matrix 
    d_dist = codistributed.build(d_local, codist); 
end 
toc 

isequal(d, d_dist) 

और उत्पादन

Elapsed time is 0.364255 seconds. 
sequential 
Elapsed time is 33.498985 seconds. 
parallel 
Lab 1: 
    lab 1 
Lab 2: 
    lab 2 
Lab 3: 
    lab 3 
Lab 4: 
    lab 4 
Elapsed time is 9.445856 seconds. 

ans = 

    1 

संपादित मैं एक नया रूप मैट्रिक्स DHess=[3x3xN] पर प्रदर्शन की जाँच कर ली। प्रदर्शन बहुत बेहतर नहीं है (10%), इसलिए यह पर्याप्त नहीं है। लेकिन हो सकता है कि आप eig को थोड़ा अलग तरीके से कार्यान्वित कर सकें? आखिरकार, वे 3x3 मैट्रिक्स हैं जिनके साथ आप काम कर रहे हैं।

+0

यह बहुत अच्छा है कि आपने इस उदाहरण को प्रदान करने के लिए समय निकाला है क्योंकि मैं इन विचारों का उपयोग कई भविष्य की परियोजनाओं के साथ कर पाऊंगा। कुछ प्रश्न: मैंने अपने कोड में 'ड्रैंज' का इस्तेमाल किया, यदि आपको 'getLocalPart' का उपयोग करना है तो इसका क्या उद्देश्य है। अपने कोड का उपयोग करके मुझे एक त्रुटि मिल रही है: 'distesspserialize लाइन क्रम में त्रुटि क्रम में त्रुटि' DHess_dist = codistributed (DHess, codistributor1d (3)); मेरे इनपुट डी का आकार लगभग 512x512x200 है, शायद आकार एक मुद्दा है; हालांकि ऐसा लगता है कि इससे कोई फर्क नहीं पड़ता कि सरणी कितनी बड़ी है, क्योंकि यह समानांतर प्रसंस्करण – Hampycalc

+0

का मुख्य उद्देश्य है, मुझे यह भी कहना चाहिए कि डी एक डबल है। – Hampycalc

+0

@Hampycalc मुझे खेद है, मैंने स्पष्ट रूप से इस तथ्य को याद किया है कि आपने 'ड्रेंज' का उपयोग किया था। मैं अपना जवाब संपादित करूंगा - आपने अपना काम पूरी तरह से विभाजित कर दिया था। मेरी गलती। – angainor

1

आप जहाँ आप निर्दिष्ट नहीं किया है ' मैंने अपना मैटलबूल खोला है, और यह तय करने वाला मुख्य कारक होगा कि आपको कितनी गति मिलती है।

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

यदि आप एक अलग मशीन पर श्रमिकों के साथ कुछ अन्य शेड्यूलर का उपयोग कर रहे हैं तो आप गति प्राप्त करने में सक्षम हो सकते हैं, लेकिन यह आपके द्वारा किए जा रहे कार्यों पर निर्भर करता है। यहां एक उदाहरण है http://www.mathworks.com/products/parallel-computing/examples.html?file=/products/demos/shipping/distcomp/paralleldemo_backslash_bench.html जो MATLAB के \ ऑपरेटर के कुछ मानक दिखाता है।

अंत में, यह ध्यान देने योग्य है कि इंडेक्सिंग वितरित सरणी दुर्भाग्य से धीमी है, खासकर MATLAB के अंतर्निहित अनुक्रमण की तुलना में। यदि आप spmd ब्लॉक के अंदर अपने कोडित वितरित सरणी के 'स्थानीय भाग' को निकाल सकते हैं और विशेष रूप से उन लोगों के साथ काम कर सकते हैं, जो भी मदद कर सकते हैं।

+0

आपके उत्तर के लिए बहुत धन्यवाद। मैं उल्लेख करना भूल गया कि मैं 6 प्रयोगशालाओं के साथ 'स्थानीय' प्रोफ़ाइल का उपयोग करके मैटलबूल खोल रहा हूं, हालांकि धारावाहिक संस्करण का उपयोग करते हुए एक एकल पुनरावृत्ति लगभग 1.7 सेकंड है, और समांतर संस्करण 5 मिनट से अधिक में एक पुनरावृत्ति को पूरा नहीं करता है। – Hampycalc

+0

ऑपरेशन (ईआईजी) स्वयं बहुप्रचारित नहीं है, और इनपुट के रूप में लिया जाने वाला मैट्रिक्स होने की आवश्यकता नहीं है क्योंकि केवल 3x3 है। हालांकि यह प्रत्येक बाहरी या आंतरिक पाश को एक अलग कोर में असाइन करने में सक्षम होने से लाभान्वित होगा। मैं 'स्थानीय भाग' निकालने और वापस रिपोर्ट करने के बारे में आपके सुझाए गए विचार का प्रयास करूंगा। – Hampycalc

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