2014-12-28 16 views
7

मैंने जूलिया में विचार किया (आर या मैटलैब के विपरीत) devectorized कोड वेक्टरकृत कोड से अक्सर तेज था। लेकिन मुझे यह मामला नहीं मिल रहा है। यहां एक उदाहरण दिया गया है:यह डेवॉक्टेड जूलिया कोड 20x से अधिक धीमा क्यों है?

julia> x = Float64[1:10000000]; 

julia> y = Array(Float64, length(x)); 

julia> @time for i = 1:length(x) y[i] = exp(x[i]) end; 
elapsed time: 7.014107314 seconds (959983704 bytes allocated, 25.39% gc time) 

julia> @time y = exp(x); 
elapsed time: 0.364695612 seconds (80000128 bytes allocated) 

वेक्टरकृत कोड इतना तेज़ क्यों है? ऐसा लगता है कि devectorized कोड 10x से अधिक स्मृति आवंटित कर रहा है। लेकिन केवल कुछ बाइट्स को वास्तव में किसी भी फ्लोट को फैलाने के लिए आवंटित करने की आवश्यकता है। क्या डिवेक्टरिज्ड कोड लिखने का कोई तरीका है ताकि यह इतनी मेमोरी आवंटित न करे, और इस प्रकार वेक्टरकृत कोड से तेज़ी से चलता है?

धन्यवाद!

+0

"_ मैंने सोचा ..._" आपको हमेशा इस प्रकृति के दावों का समर्थन करने के लिए कुछ सबूत देना चाहिए। – csmckelvey

+2

निश्चित रूप से, यहां एक पोस्ट है जो दर्शाता है कि जूलिया में कितना तेज़ डिवेक्टरिज्ड कोड हो सकता है: http://www.johnmyleswhite.com/notebook/2013/12/22/the-relationship-between-vectorized-and-devectorized-code/ – Jeff

उत्तर

10

पर विचार करें निम्नलिखित कोड का टुकड़ा:

x = Float64[1:10000000]; 
y = Array(Float64, length(x)); 
function nonglobal_devec!(x,y) 
    for i = 1:length(x) y[i] = exp(x[i]) end 
end 
function nonglobal_vec(x) 
    exp(x) 
end 
@time nonglobal_devec!(x,y); 
@time y = nonglobal_vec(x); 
x = Float64[1:10000000]; 
y = Array(Float64, length(x)); 
@time for i = 1:length(x) y[i] = exp(x[i]) end 
@time y = exp(x) 

जो बार

A: elapsed time: 0.072701108 seconds (115508 bytes allocated) 
B: elapsed time: 0.074584697 seconds (80201532 bytes allocated) 
C: elapsed time: 2.029597656 seconds (959990464 bytes allocated, 22.86% gc time) 
D: elapsed time: 0.058509661 seconds (80000128 bytes allocated) 

अजीब एक बाहर देता है, सी, due to it operating in the global scope है, जहां प्रकार अनुमान परिचालन नहीं करता है, और एस निचला कोड उत्पन्न होता है।

ए और बी के बीच सापेक्ष समय कुछ भिन्नता के अधीन होते हैं क्योंकि पहली बार उनके द्वारा उपयोग किए जाने वाले कार्यों को संकलित किया जाता है। हम इसे फिर से चलाने अगर हम

A2: elapsed time: 0.038542212 seconds (80 bytes allocated) 
B2: elapsed time: 0.063630172 seconds (80000128 bytes allocated) 

जो भावना ए 2 स्मृति को आबंटित नहीं है (कि 80 बाइट्स समारोह की वापसी मान के लिए है) बनाता है, और बी 2 एक नया वेक्टर बनाता है मिलता है। यह भी ध्यान रखें कि बी 2 समान मात्रा में स्मृति आवंटित करता है क्योंकि डी करता है - पहली बार अतिरिक्त संकलन के लिए आवंटित स्मृति थी।

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

+2

धन्यवाद, इयान, यह मेरे मुकाबले एक बेहतर जवाब है। – StefanKarpinski

+0

मैं इस धागे को हाइजैक करने जा रहा हूं कि यह पूछने के लिए कि क्या ए 2 में 80 बाइट्स को फ़ंक्शन कहा जाता है, हर बार आवंटित किया जाता है? उदाहरण के लिए, यदि वह फ़ंक्शन लूप में है जो इसे 10^5 बार कहते हैं, तो 80 * 10^5 बाइट आवंटित किए जाएंगे? – Nick

+0

बहुत यकीन है कि यह नहीं होगा, जो जांचना आसान है - यह सिर्फ एक आरपीएल चीज है। हालांकि आरईपीएल में चीजें अजीब हैं! यदि आप उस कमांड को लूप में रखना चाहते थे, तो आरईपीएल में, मुझे लगता है कि आपको शायद 80 बाइट मिलेगा, जो लूप के आसपास आखिरी बार मूल्य होगा। – IainDunning

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