2012-02-09 30 views
9

मुझे कुछ गणनाओं की संख्याओं की एक बड़ी सूची करने की आवश्यकता है।पायथन numpy सरणी बनाम सूची

क्या सरणी.एरे या numpy.array विशिष्ट सरणी पर महत्वपूर्ण प्रदर्शन बढ़ावा प्रदान करते हैं?

मैं मैं सिर्फ का उपयोग और मूल्यों को संशोधित करने में सक्षम होना चाहिए, सरणियों पर जटिल जोड़तोड़ करने के लिए नहीं है,

उदा

import numpy 
x = numpy.array([0] * 1000000) 
for i in range(1,len(x)): 
    x[i] = x[i-1] + i 

इसलिए मैं वास्तव में संयोजन, टुकड़ा करने की क्रिया, आदि

भी आवश्यकता होगी, नहीं किया जाएगा, ऐसा लगता है सरणी एक त्रुटि फेंकता की तरह अगर मैं मान जो सी लंबे में फिट नहीं आवंटित करने के लिए प्रयास करें:

import numpy 
a = numpy.array([0]) 
a[0] += 1232234234234324353453453 
print(a) 

कंसोल पर मैं:

a[0] += 1232234234234324353453453 
OverflowError: Python int too large to convert to C long 

वहाँ मुझे unbo में डाल देता है कि सरणी की भिन्नता है अवांछित पायथन पूर्णांक? या ऐसा करने से पहले तरीके से सरणी होने का बिंदु दूर हो जाएगा?

+0

यह भी देखें [cpython बनाम साइथन बनाम numpy सरणी प्रदर्शन] (http://stackoverflow.com/questions/22514730/cpython-vs-cython-vs-numpy-array-performance) – Trilarion

उत्तर

8

आपका पहला उदाहरण तेज हो सकता है। पाइथन लूप और एक numpy सरणी में अलग-अलग वस्तुओं तक पहुंच धीमी है। बजाय vectorized संचालन का उपयोग करें: तय आकार सी पूर्णांकों की तुलना में इस मामले में धीमी होगी

a = np.array([0], dtype=object) 
a[0] += 1232234234234324353453453 

अंकगणितीय आपरेशनों:

import numpy as np 
x = np.arange(1000000).cumsum() 

आप numpy सरणी के लिए असीम अजगर पूर्णांकों डाल सकते हैं।

11

आपको पहले सरणी और सूचियों के बीच अंतर को समझने की आवश्यकता है।

एक सरणी संगत स्मृति के ब्लॉक को कुछ प्रकार (जैसे पूर्णांक) के तत्वों से युक्त है।

आप इसे बनाने के बाद किसी सरणी के आकार को नहीं बदल सकते हैं।
इसलिए यह एक सरणी में प्रत्येक पूर्णांक तत्व का निश्चित आकार, उदा। 4 निवाले।

दूसरी ओर, एक सूची महज एक पतों (जो भी एक निश्चित आकार है) की "सरणी" है।

लेकिन तब प्रत्येक तत्व कुछ बाकी स्मृति में है, जो वास्तविक पूर्णांक है कि आप के साथ काम करना चाहते हैं का पता रखती है। बेशक, इस पूर्णांक का आकार सरणी के आकार के लिए अप्रासंगिक है। इस प्रकार आप हमेशा एक नया (बड़ा) पूर्णांक बना सकते हैं और सरणी के आकार को प्रभावित किए बिना पुराने को "प्रतिस्थापित" कर सकते हैं, जिसमें केवल पूर्णांक के पता पते हैं।

बेशक

, एक सूची के इस सुविधा लागत से आता है: पूर्णांकों पर गणित प्रदर्शन अब, सरणी के लिए एक स्मृति पहुंचने की आवश्यकता हो प्लस पूर्णांक ही करने के लिए एक स्मृति का उपयोग, प्लस समय यह करने के लिए ले जाता है अधिक पूर्ण आवंटित करें (यदि आवश्यक हो), प्लस पुराना पूर्णांक (यदि आवश्यक हो) को हटाने के लिए आवश्यक समय आवंटित करें। तो हाँ, यह धीमा हो सकता है, इसलिए आपको सावधान रहना होगा कि आप सरणी के अंदर प्रत्येक इंटीजर के साथ क्या कर रहे हैं।

+0

अंतिम पैराग्राफ समान रूप से numpy arrays पर लागू होता है यदि आप वेक्टरीकृत ऑपरेशंस का उपयोग नहीं करते हैं (जैसे ओपी के पहले उदाहरण में) का उपयोग नहीं किया गया है तो निश्चित आकार के पूर्णांक का। यह * नहीं * कारण है कि numpy arrays तेजी से हो सकता है। – jfs

0

क्या array.array या numpy.array विशिष्ट सरणी पर महत्वपूर्ण प्रदर्शन बढ़ावा प्रदान करते हैं?

यह आपके द्वारा किए जा रहे कार्यों के आधार पर हो सकता है।

या ऐसा करने से पहले तरीके से सरणी होने का बिंदु दूर हो जाएगा?

बहुत अधिक, हाँ।

1

क्या array.array या numpy.array विशिष्ट सरणी पर महत्वपूर्ण प्रदर्शन को बढ़ावा देता है?

मैं इस निम्न कोड के साथ एक सा परीक्षण करने के लिए करने की कोशिश की:

import timeit, math, array 
from functools import partial 
import numpy as np 

# from the question 
def calc1(x): 
    for i in range(1,len(x)): 
     x[i] = x[i-1] + 1 

# a floating point operation 
def calc2(x): 
    for i in range(0,len(x)): 
     x[i] = math.sin(i) 

L = int(1e5) 

# np 
print('np 1: {:.5f} s'.format(timeit.timeit(partial(calc1, np.array([0] * L)), number=20))) 
print('np 2: {:.5f} s'.format(timeit.timeit(partial(calc2, np.array([0] * L)), number=20))) 

# np but with vectorized form 
vfunc = np.vectorize(math.sin) 
print('np 2 vectorized: {:.5f} s'.format(timeit.timeit(partial(vfunc, np.arange(0, L)), number=20))) 

# with list 
print('list 1: {:.5f} s'.format(timeit.timeit(partial(calc1, [0] * L), number=20))) 
print('list 2: {:.5f} s'.format(timeit.timeit(partial(calc2, [0] * L), number=20))) 

# with array 
print('array 1: {:.5f} s'.format(timeit.timeit(partial(calc1, array.array("f", [0] * L)), number=20))) 
print('array 2: {:.5f} s'.format(timeit.timeit(partial(calc2, array.array("f", [0] * L)), number=20))) 

और परिणाम थे कि सूची यहाँ सबसे तेजी से कार्यान्वित (अजगर 3.3, NumPy 1.8):

np 1: 2.14277 s 
np 2: 0.77008 s 
np 2 vectorized: 0.44117 s 
list 1: 0.29795 s 
list 2: 0.66529 s 
array 1: 0.66134 s 
array 2: 0.88299 s 

कौन सा लगता है कि counterintuitive है। इन सरल उदाहरणों के लिए पर numpy या array का उपयोग करने में कोई लाभ नहीं प्रतीत होता है।

0

a=numpy.array(number_of_elements, dtype=numpy.int64) का उपयोग करें जो आपको 64-बिट पूर्णांकों की एक श्रृंखला प्रदान करना चाहिए। ये -2^63 और (2^63) -1 के बीच किसी भी पूर्णांक संख्या को स्टोर कर सकते हैं (लगभग -10^1 9 और 10^1 9 के बीच) जो आमतौर पर पर्याप्त से अधिक होता है।

2

अधिकांश उपयोगों के लिए, सूचियां उपयोगी हैं। कभी-कभी numpy arrays के साथ काम करना उदाहरण के लिए अधिक सुविधाजनक हो सकता है।

a=[1,2,3,4,5,6,7,8,9,10] 

b=[5,8,9] 

एक सूची 'एक' और तुम 'बी' सूची में दिए गए असतत सूचकांक एक सूची में तत्वों का उपयोग करना चाहते हैं

b[a] 

काम नहीं करेगा लेखन पर विचार करें।

लेकिन जब आप उन्हें सरणियों के रूप में उपयोग, तो आप बस

b[a] 

सरणी के रूप में उत्पादन प्राप्त करने के लिए लिख सकते हैं ([6,9,10])।

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