2016-05-18 9 views
5

में प्रत्येक बिंदु के बीच दूरी की गणना करने का सबसे तेज़ तरीका मेरी परियोजना में मुझे एक सरणी में संग्रहीत प्रत्येक बिंदु के बीच यूक्लिडियन दूरी की गणना करने की आवश्यकता है। एंट्री सरणी एक 2 डी numpy सरणी है जिसमें 3 कॉलम हैं जो निर्देशांक (x, y, z) हैं और प्रत्येक पंक्तियां एक नए बिंदु को परिभाषित करती हैं।पाइथन

मैं अपने परीक्षण मामलों में 5000 - 6000 अंक के साथ सामान्य रूप से काम कर रहा हूं।

मेरा पहला एल्गोरिदम साइथन और मेरा दूसरा numpy का उपयोग करता है। मुझे लगता है कि मेरा numpy एल्गोरिदम साइथन से तेज है।

संपादित करें: 6000 अंकों के साथ:

numpy 1.76 s/cython 4.36 रों

यहाँ मेरी cython कोड है:

cimport cython 
from libc.math cimport sqrt 
@cython.boundscheck(False) 
@cython.wraparound(False) 
cdef void calcul1(double[::1] M,double[::1] R): 

    cdef int i=0 
    cdef int max = M.shape[0] 
    cdef int x,y 
    cdef int start = 1 

    for x in range(0,max,3): 
    for y in range(start,max,3): 

     R[i]= sqrt((M[y] - M[x])**2 + (M[y+1] - M[x+1])**2 + (M[y+2] - M[x+2])**2) 
     i+=1 

    start += 1 

एम प्रारंभिक प्रविष्टि सरणी के एक स्मृति दृश्य लेकिन flatten() कर रहा है फंक्शन calcul1() की कॉल से पहले numpy, आर सभी परिणामों को स्टोर करने के लिए 1 डी आउटपुट सरणी का मेमोरी व्यू है।

यहाँ मेरी Numpy कोड है: पंक्तियों और अंक स्तंभों के रूप में के रूप में निर्देशांक (एक्स, वाई, जेड) के लिए समारोह कॉल करने से पहले

def calcul2(M): 

    return np.sqrt(((M[:,:,np.newaxis] - M[:,np.newaxis,:])**2).sum(axis=0)) 

यहाँ एम प्रारंभिक प्रविष्टि सरणी लेकिन transpose() numpy कर रहा है।

इसके अलावा यह numpy फ़ंक्शन काफी दृढ़ है क्योंकि यह लौटने वाला सरणी व्यवस्थित है। यह एन सरणी द्वारा n अंकों की संख्या के साथ एन है और प्रत्येक बिंदु में एक पंक्ति और एक स्तंभ है।

cpdef test(): 

    cdef double[::1] Mf 
    cdef double[::1] out = np.empty(17998000,dtype=np.float64) # (6000² - 6000)/2 

    M = np.arange(6000*3,dtype=np.float64).reshape(6000,3) # Example array with 6000 points 
    Mf = M.flatten() #because my cython algorithm need a 1D array 
    Mt = M.transpose() # because my numpy algorithm need coordinates as rows 

    calcul2(Mt) 

    calcul1(Mf,out) 

मैंने कुछ गलत यहां क्या कर रहा हूँ: तो उदाहरण दूरी के लिए अटल बिहारी पंक्ति एक और स्तंभ बी के चौराहे सूचकांक

यहाँ है मैं उन्हें (cython समारोह) कैसे फोन पर संग्रहीत किया जाता है? मेरी परियोजना के लिए दोनों पर्याप्त तेज़ नहीं हैं।

1: क्या numpy की गति को हरा करने के लिए मेरे साइथन कोड को बेहतर बनाने का कोई तरीका है?

2: क्या मेरे numpy कोड को और भी तेजी से गणना करने के लिए कोई तरीका है?

3: या कोई अन्य समाधान, लेकिन यह एक पायथन/साइथन (समानांतर कंप्यूटिंग की तरह) होना चाहिए?

धन्यवाद।

+1

यदि आपको दूरी की आवश्यकता नहीं है और केवल अंतर/रैंकिंग की परवाह है, तो आप sqrt से छुटकारा पा सकते हैं, जो आपकी गणना का सबसे धीमा हिस्सा होना चाहिए। हो सकता है कि आप एक तेज़ sqrt का भी उपयोग कर सकें, जो सटीक नहीं है या कुछ अन्य मीट्रिक (उदा। टैक्सीकैब) का उपयोग नहीं कर सकता है। – sascha

+2

5000 से 6000 अंक के साथ, आपके मैट्रिक्स में लगभग 30 मिलियन प्रविष्टियां होंगी। एक वर्ग रूट 30 मीटर बार कंप्यूटिंग धीमा होने के लिए बाध्य है। क्या आपको वास्तव में पूर्ण, घने मैट्रिक्स की आवश्यकता है? कंप्यूटिंग के बाद मैट्रिक्स के साथ आप क्या कर रहे हैं? –

+0

साइथन से कितनी तेज है? – sebacastroh

उत्तर

5

सुनिश्चित नहीं हैं कि जहाँ आप अपने समय हो रही है, लेकिन आप scipy.spatial.distance उपयोग कर सकते हैं: एहसास है कि अपने उत्पादन सममित है

%timeit calcul2(M) 
1000 loops, best of 3: 313 µs per loop 

%timeit sd.cdist(M.T, M.T) 
10000 loops, best of 3: 86.4 µs per loop 

महत्वपूर्ण बात, अपने भी उपयोगी:

M = np.arange(6000*3, dtype=np.float64).reshape(6000,3) 
np_result = calcul2(M) 
sp_result = sd.cdist(M.T, M.T) #Scipy usage 
np.allclose(np_result, sp_result) 
>>> True 

समय

np.allclose(sp_result, sp_result.T) 
>>> True 

एक विकल्प केवल इस सरणी के ऊपरी त्रिभुज की गणना करना है:

%timeit sd.pdist(M.T) 
10000 loops, best of 3: 39.1 µs per loop 

संपादित करें: यह निश्चित नहीं है सूचकांक आप ज़िप करना चाहते, लगता है कि आप यह दोनों तरीकों से कर रहे होंगे? तुलना के लिए अन्य सूचकांक को ज़िपित करना:

%timeit sd.pdist(M) 
10 loops, best of 3: 135 ms per loop 

अभी भी आपके वर्तमान NumPy कार्यान्वयन से लगभग 10x तेज है।

+0

जिज्ञासा से, आपने इन समय के लिए 'एम' का किस आकार का उपयोग किया था? ओपी में –

+0

@ स्वेनमार्कैच '(6000, 3) ', मैंने इसे और अधिक स्पष्ट करने के लिए अपना प्रश्न अपडेट कर दिया है। – Daniel

+0

क्षमा करें, लेकिन मुझे समझ में नहीं आता कि 'एमटी' क्या है? क्या यह 'एम' का ऊपरी त्रिकोण है? – UserAt