2016-09-05 12 views
5

मैं numba का उपयोग करके 0xके साथ एक 'वेक्सपी' (एक वेक्टर में स्केलर एकाधिक को एक वेक्टर में जोड़ना और परिणाम को पहले असाइन करना) करना चाहता हूं। निम्नलिखित परीक्षण करते हुए, मैंने देखा कि लूप लिखना a += c * b करने से बहुत तेज था।नुम्बा: मैन्युअल लूपिंग एक + = सी * बी से numpy arrays के साथ तेजी से लूपिंग?

मुझे इसकी उम्मीद नहीं थी। इस व्यवहार का कारण क्या है? ध्यान में रखने की

import numpy as np 
from numba import jit 

x = np.random.random(int(1e6)) 
o = np.random.random(int(1e6)) 
c = 3.4 

@jit(nopython=True) 
def test1(a, b, c): 
    a += c * b 
    return a 

@jit(nopython=True) 
def test2(a, b, c): 
    for i in range(len(a)): 
     a[i] += c * b[i] 
    return a 

%timeit -n100 -r10 test1(x, o, c) 
>>> 100 loops, best of 10: 2.48 ms per loop 
%timeit -n100 -r10 test2(x, o, c) 
>>> 100 loops, best of 10: 1.2 ms per loop 

उत्तर

2

एक बात numba में 'मैनुअल पाशन' है बहुत तेजी से, सी-पाश numpy आपरेशन द्वारा प्रयोग किया जाता के रूप में अनिवार्य रूप से एक ही है।

पहले उदाहरण में दो ऑपरेशन हैं, एक अस्थायी सरणी (c * b) आवंटित/गणना की जाती है, तो उस अस्थायी सरणी को a में जोड़ा जाता है। दूसरे उदाहरण में, दोनों गणना एक ही लूप में हो रही हैं जिसमें कोई मध्यवर्ती परिणाम नहीं है।

सिद्धांत में, numba लूप फ्यूज कर सकता है और # 2 के समान करने के लिए # 1 अनुकूलित कर सकता है, लेकिन ऐसा लगता है कि ऐसा नहीं लगता है। यदि आप सिर्फ numpy ops को अनुकूलित करना चाहते हैं, numexpr भी एक लायक हो सकता है क्योंकि यह बिल्कुल ठीक से डिजाइन किया गया था - हालांकि शायद स्पष्ट फ़्यूज्ड लूप से बेहतर नहीं होगा।

In [17]: import numexpr as ne 

In [18]: %timeit -r10 test2(x, o, c) 
1000 loops, best of 10: 1.36 ms per loop 

In [19]: %timeit ne.evaluate('x + o * c', out=x) 
1000 loops, best of 3: 1.43 ms per loop 
+0

आपके उत्तर के लिए धन्यवाद। मैंने वास्तव में सोचा था कि '+ =' ऑपरेटर के उपयोग से, 'numba' इसे समझने में सक्षम होगा और इसे कुशलतापूर्वक करेगा क्योंकि यह बहुत स्पष्ट है। मुझे लगता है कि यह यहां एक विशेष मामला है, उदाहरण के लिए गति के संदर्भ में डॉट उत्पाद 'np.dot' को पीटा नहीं जा सकता है। – NoBackingDown

+0

यह कुछ हद तक स्पर्शपूर्ण है, लेकिन वास्तव में 'np.dot' एक विशेष मामला है। 'numpy' आपके द्वारा इंस्टॉल किए गए बीएलएएस को कॉल करेगा, जो इंटेल के एमकेएल की तरह बहुत कुछ हो सकता है। – chrisb

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