2013-10-21 9 views
5

मैं इस समीकरण (और एक ही रूप के कई अन्य) के लिए vectorized कोड का उत्पादन करने के कोशिश कर रहा हूँ में डबल योग vectorize करने के लिए यह परिवर्तन Rmn(t) है इसलिए मैं बेसेल और sin फ़ंक्शंस का पूर्व-कंप्यूटिंग कर रहा हूं। फिलहाल मेरे कोड इस तरह दिखता है:कैसे matlab

for iR = 1:nR 
    p(:, iR) = sum(Rmn.*J0m(:, :, iR),1)*sinanz; 
end 

M, N मेरी योग और R में पदों की संख्या रहे हैं, Zr की संख्या रहे हैं और z मैं उपयोग कर रहा हूँ समन्वय करता है। Rmn एक M*N मैट्रिक्स है। J0m एक M*N*R सरणी है। यह M*R मैट्रिक्स है जिसे N बार दोहराया गया है। sinanz एक N*Z मैट्रिक्स है। J0m और sinanz पूर्व-गणना की जाती हैं और परिवर्तित नहीं होती हैं।

यह काम करता है लेकिन धीमा है और इसलिए मैं इसे अनुकूलित करने की कोशिश कर रहा हूं। मुझे लगा कि पहला कदम J0m को कम करना होगा, इसलिए यह केवल m*R है लेकिन मैं यह नहीं समझ सकता कि कैसे। मैं यह कैसे करना है और इसे सामान्य रूप से अनुकूलित करने के तरीके पर कोई सुझाव ढूंढ रहा हूं।

+0

क्या आपने पूर्व-आवंटित 'पी' है? यही है, लूप से पहले 'पी = शून्य (जेड, एनआर);' –

+0

हाँ मैंने यह किया है। छवि और 'कोड' को ठीक करने के लिए भी धन्यवाद। – Jazradel

उत्तर

5

आप शायद पहले से ही जानते हैं, आप पाश से पहले पूर्व आवंटित चाहिए p:

p = zeros(Z, nR); 

इस, प्रत्येक यात्रा से बढ़ काफी पाश को तेज करने से सरणी p से बचाता है।

आप bsxfun के आधार पर पूरी बात vectorize सकता है:

% C ≣ M×N×R array of all products Rmn·J0m 
C = bsxfun(@times, Rmn, J0m); 

% D ≣ M×N×R×Z array of all products C·sinanz 
D = bsxfun(@times, C, permute(sinanz, [3 1 4 2])); 

% Sum in M and N directions, and re-order 
p = permute(sum(sum(D,1),2), [4 3 1 2]); 

लेकिन मुझे शक है यह तेजी से हो रहा है; MATLAB (पढ़ें: बीएलएएस) 2 डी matrices के साथ बहुत तेज है, लेकिन आमतौर पर अधिक डी डी arrays के साथ बहुत अच्छा नहीं है।

मेरा सुझाव है कि आप bsxfun पढ़ लें; यह वर्णन करने के तरीके में J0m सरणी M × R को कम करने का भी तरीका है।

बेशक

, आप ठीक ढंग से अपने चर को परिभाषित करते हुए permute रों से छुटकारा पाने, तो चलो दोनों फंस और vectorized कोड के 'आदर्श' संस्करणों में एक छोटे से परीक्षण करते हैं कर सकते हैं:

%% Initialize some variables 

% Number of tests 
TESTS = 1e4; 

% Your dimensions 
M = 5; nR = 4; 
N = 2; Z = 3; 

% Some dummy data 
Rmn = rand(M,N); 
sinanz = rand(N,Z); 
J0m = rand(M,nR); % NOTE: J0m doesn't have to be 3D anymore by using bsxfun 

%% Test 1: your own version, optimized 

% Start test 
start = tic; 

% Repeat the test a couple of times to get a good average 
for ii = 1:TESTS 
    p1 = zeros(Z,nR); 
    for iR = 1:nR 
     p1(:, iR) = sum(bsxfun(@times,Rmn,J0m(:, iR)), 1)*sinanz; 
    end  
end 
stop = toc(start); 

% Average execution time 
fprintf(1, 'Average time of looped version: %f seconds.\n', stop/TESTS); 

%% Vectorized version, using 4D arrays: 

% Don't make the permutes part of the test 
J0m = permute(J0m, [1 3 2]); 
sinanz = permute(sinanz, [3 1 4 2]); 

% Start test 
start = tic; 

% Repeat the test a couple of times to get a good average 
for ii = 1:TESTS 
    C = bsxfun(@times, Rmn, J0m); 
    D = bsxfun(@times, C, sinanz); 
    p2 = sum(sum(D,1),2); 

end 
stop = toc(start); 

% Average execution time 
fprintf(1, 'Average time of vectorized version: %f seconds.\n', stop/TESTS); 

%% Check for equality 

maxDifference = max(max(p1 - squeeze(p2)')) 

परिणाम:

Average time of looped version : 0.000054 seconds. 
Average time of vectorized version: 0.000023 seconds. 
maxDifference = 
    4.440892098500626e-016 

जो बहुत अच्छा लगता है! हालांकि,

M = 50; nR = 40; 
N = 20; Z = 30; 

का उपयोग कर आप

Average time of looped version : 0.000708 seconds. 
Average time of vectorized version: 0.009835 seconds. 
maxDifference = 
    8.526512829121202e-014 

तो vectorized संस्करण सिर्फ परिमाण looped संस्करण की तुलना में धीमी का आदेश मिल गया मिलता है।

बेशक, your mileage may vary, लेकिन घर लेना संदेश यह है कि आपको इस अंतर को आयामों को बढ़ाने के लिए बदतर और बदतर होने की उम्मीद करनी चाहिए।

तो, अंत में:

  • अगर आपके आयाम बड़े हैं, पाश के साथ चिपके रहते हैं। वे छोटे हैं, तो भी लूप का उपयोग करें - यह सिर्फ अतः ज्यादा vectorized संस्करण :)
  • पूर्व आवंटित करने के लिए p चर
  • उपयोग bsxfun स्मृति पदचिह्न को कम करने के लिए सुनिश्चित करें की तुलना में आंखों पर आसान है (लेकिन यह गति को और अधिक नहीं बढ़ाएगा)
+0

आपकी मदद के लिए धन्यवाद। मैंने टेस्ट 1 की कोशिश की और मेरे मूल संस्करण के रूप में चलाने में लगभग दोगुना लग रहा है (लगभग आयामों के समान ही रहता है), ऐसा लगता है कि मेरे पास अब इष्टतम समाधान है। मैं मॉडल को एम = एन = 50 के साथ चलाने का लक्ष्य रख रहा था, इसलिए दूसरा कोई भी मदद करने वाला नहीं है। यद्यपि विकल्प देखने के लिए अच्छा है। – Jazradel