2011-09-23 8 views
6

मैं एक ऐसा फ़ंक्शन लिखने की कोशिश कर रहा हूं जो किसी सरणी पर गणितीय ऑपरेशन करता है और परिणाम देता है। एक सरल उदाहरण हो सकता है:जगह में numpy फ़ंक्शन आउटपुट सरणी को बदलना

def original_func(A): 
    return A[1:] + A[:-1] 

गति-अप के लिए और प्रत्येक समारोह कॉल के लिए एक नया उत्पादन सरणी का आवंटन से बचने के लिए, मैं एक तर्क के रूप उत्पादन सरणी है, और जगह में यह परिवर्तन करने के लिए करना चाहते हैं:

def inplace_func(A, out): 
    out[:] = A[1:] + A[:-1] 

हालांकि, जब निम्नलिखित तरीके से इन दोनों कार्यों बुला,

A = numpy.random.rand(1000,1000) 
out = numpy.empty((999,1000)) 

C = original_func(A) 

inplace_func(A, out) 

मूल कार्य हो रहा है दोगुनी गति से इन-प्लेस फ़ंक्शन के रूप में। इसे कैसे समझाया जा सकता है? क्या इन-प्लेस फ़ंक्शन तेज नहीं होना चाहिए क्योंकि इसे स्मृति आवंटित करने की आवश्यकता नहीं है?

उत्तर

5

मुझे लगता है कि है कि इसका जवाब निम्नलिखित है:

दोनों ही मामलों में, आप A[1:] + A[:-1] गणना, और दोनों ही मामलों में, आप वास्तव में एक मध्यवर्ती मैट्रिक्स पैदा करते हैं।

क्या दूसरे मामले में होता है, हालांकि, कि आप स्पष्ट रूप से एक सुरक्षित स्मृति में पूरे बड़ा नव आवंटित सरणी कॉपी है। इस तरह की एक सरणी की प्रतिलिपि मूल ऑपरेशन के समान ही होती है, इसलिए आप वास्तव में समय को दोगुना करते हैं।

योग-अप के लिए, पहले मामले में, आप कार्य करें:

compute A[1:] + A[:-1] (~10ms) 

दूसरे मामले में, आप

compute A[1:] + A[:-1] (~10ms) 
copy the result into out (~10ms) 
+1

एक समाधान के रूप में: मुझे लगता है * यदि आप छोरों अपने आप को ऐसा करने के लिए ओलिवियर के जवाब में वर्णित मध्यवर्ती सरणियों से बचने के लिए होगा *। या शायद http://code.google.com/p/numexpr/ जैसी कुछ आपकी मदद कर सकती है? यह [प्रश्न] (http://stackoverflow.com/questions/2937669/linear-combinations-in-python-numpy) भी प्रासंगिक दिखता है। – gspr

+0

मुझे लगता है कि आप इसे करके इंटरमीडिएट सरणी से बच सकते हैं: 'बाहर [:] = ए [1:]; बाहर + = ए [: - 1] 'बेशक आपका वास्तविक अहंकार शायद सुव्यवस्थित होने के लिए कठिन होगा। बेशक हर कीमत पर लूप से बचने की कोशिश करें। अक्सर रचनात्मक चीजें होती हैं जो आप जमा और ufuncs के साथ कर सकते हैं .. – Paul

-1

मैं Olivers स्पष्टीकरण के साथ सहमत हैं। यदि आप ऑपरेशन को ऑपरेशन करना चाहते हैं, तो आपको अपने सरणी को मैन्युअल रूप से लूप करना होगा। यह बहुत धीमा होगा, लेकिन यदि आपको गति की आवश्यकता है तो आप साइथन का सहारा ले सकते हैं जो आपको शुद्ध सी कार्यान्वयन की गति देता है।

12

आप में जगह कार्रवाई करने के लिए चाहते हैं,

 
def inplace_func(A, out): 
    np.add(A[1:], A[:-1], out) 

यह किसी भी temporaries (जो A[1:] + A[:-1]) करता है का निर्माण नहीं करता है।

सभी Numpy द्विआधारी संचालन, इसी कार्य यहाँ सूची देखें: http://docs.scipy.org/doc/numpy/reference/ufuncs.html#available-ufuncs

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