2013-05-25 11 views
7

मेरे पास कई सस्पिस स्पैस मैट्रिस (वर्तमान में सीएसआर प्रारूप में) हैं जिन्हें मुझे घने numpy 1D वेक्टर के साथ गुणा करने की आवश्यकता है। वेक्टर G कहा जाता है:Scipy Sparse Matrix - घने वेक्टर गुणन प्रदर्शन - ब्लॉक बनाम बड़े मैट्रिक्स

print G.shape, G.dtype 
(2097152,) complex64 

प्रत्येक विरल मैट्रिक्स आकार (16384,2097152) है और बहुत विरल है। घनत्व लगभग 4.0e-6 है। मेरे पास spmats नामक इन स्पैर मैट्रिक्स में से 100 की एक सूची है।

मैं आसानी से तो जैसे G के साथ प्रत्येक मैट्रिक्स गुणा कर सकते हैं:

res = [spmat.dot(G) for spmat in spmats] 

यह अपेक्षा के अनुरूप आकार (16384,) के घने वैक्टर की एक सूची का परिणाम है।

मेरा आवेदन काफी कार्यक्षमता के लिए महत्वपूर्ण है, और इसलिए मैं एक वैकल्पिक, पहले एक बड़े sparce मैट्रिक्स में सभी विरल मैट्रिक्स को श्रेणीबद्ध करने के लिए, और उसके बाद तो जैसे dot() का केवल एक कॉल का उपयोग है जो करने की कोशिश की:

import scipy.sparse as sp 
SPMAT = sp.vstack(spmats, format='csr') 
RES = SPMAT.dot(G) 

यह एक लंबे वेक्टर RES में परिणाम देता है जिसमें (1638400,) आकार होता है, और उम्मीद के अनुसार res में सभी परिणाम वैक्टरों का एक समेकित संस्करण है। मैंने जांच की है कि परिणाम समान हैं।

शायद मैं पूरी तरह गलत हूं, लेकिन मुझे उम्मीद है कि दूसरा मामला पहले से तेज होना चाहिए, क्योंकि बहुत कम संख्या में कॉल, स्मृति आवंटन, अजगर वस्तुओं का निर्माण, पायथन लूप आदि शामिल नहीं हैं। स्पैर मैट्रिस को संयोजित करने के लिए आवश्यक समय के बारे में परवाह करें, केवल परिणाम की गणना करने का समय। %timeit के अनुसार, हालांकि:

%timeit res = [spmat.dot(G) for spmat in spmats] 
10 loops, best of 3: 91.5 ms per loop 
%timeit RES = SPMAT.dot(G) 
1 loops, best of 3: 389 ms per loop 

मैं देख लिया है कि मैं स्मृति से बाहर या तो आपरेशन में नहीं चल रहा हूँ, और गड़बड़ कुछ भी नहीं हो रहा जा रहा है। क्या मैं पागल हूँ, या यह वास्तव में अजीब है? क्या इसका मतलब यह है कि सभी स्पैस मैट्रिक्स-वेक्टर उत्पादों को ब्लॉक में, एक समय में कुछ पंक्तियों को तेजी से बनाने के लिए किया जाना चाहिए? जहां तक ​​मैं समझता हूं, एक घने वेक्टर के साथ स्पैर मैट्रिक्स गुणा समय nonzero तत्वों की संख्या में रैखिक होना चाहिए, जो उपरोक्त दो मामलों में अपरिवर्तित है। इतना अंतर क्या हो सकता है?

मैं के साथ 4 जीबी राम एक सिंगल कोर Linux मशीन पर चल रहा हूँ, का उपयोग कर EPD7.3

संपादित करें:

import scipy.sparse as sp 
import numpy as n 

G = n.random.rand(128**3) + 1.0j*n.random.rand(128**3) 

spmats = [sp.rand (128**2, 128**3, density = 4e-6, format = 'csr', dtype=float64) for i in range(100)] 
SPMAT = sp.vstack(spmats, format='csr') 

%timeit res = [spmat.dot(G) for spmat in spmats] 
%timeit RES = SPMAT.dot(G) 
:

यहाँ एक छोटा सा उदाहरण है कि मेरे लिए समस्या पुनरुत्पादित करता है

मुझे मिलता है:

1 loops, best of 3: 704 ms per loop 
1 loops, best of 3: 1.34 s per loop 

इस मामले में प्रदर्शन अंतर इतना बड़ा नहीं है जैसा कि मेरे अपने स्पैर मैट्रिस के साथ है जिसमें कुछ संरचना है (शायद कैशिंग के कारण) लेकिन मैट्रिस को जोड़ना अभी भी बदतर है।

मैंने दोनों 10.1 और 12.0 दोनों के साथ प्रयास किया है।

+1

मैं इसे पुन: पेश नहीं कर सकता: एकल डॉट उत्पाद मेरे लिए 5 गुना तेज है। चूंकि मैंने आपके द्वारा वर्णित किए जाने वाले कार्यों को सावधानीपूर्वक करने की कोशिश की है, क्या आप यह सुनिश्चित करने के लिए एक न्यूनतम कार्य उदाहरण पोस्ट कर सकते हैं कि हम वही काम कर रहे हैं? – jorgeca

+0

@jorgeca समस्या को आजमाने और पुन: उत्पन्न करने के लिए समय निकालने के लिए धन्यवाद। मैंने अपने प्रश्न को सिर्फ एक कामकाजी उदाहरण के साथ संपादित किया है जो मैं कर रहा हूं। –

+0

धन्यवाद। मैं आपके परिणामों को पुन: उत्पन्न नहीं कर सकता (एससीआई 0.12 में) लेकिन मेरे लिए सूची समझ 5x (!) धीमी है जब 'जी' में' dtype = np.complex64' है जैसा आपने कहा था, और दोनों दृष्टिकोण समान रूप से तेज़ होते हैं जब 'जी' 'dtype = np.complex128' है। – jorgeca

उत्तर

4

मुझे प्रश्न में वर्णित अजीब व्यवहार का कोई कारण नहीं मिला है, हालांकि मुझे अपने गणना को तेज करने का एक तरीका मिला है जो अन्य लोगों के लिए उपयोगी हो सकता है।

क्योंकि मेरे विशेष मामले में मैं एक फ्लोट 32 स्पैर्स मैट्रिक्स और एक जटिल 64 घने वेक्टर के उत्पाद की गणना कर रहा हूं, मैं वास्तविक और काल्पनिक घटकों को अलग से गुणा कर सकता हूं। यह मुझे 4x गति प्रदान करता है।

यह SPMAT.shape == (16384000, 2097152) साथ 2.35s लेता है:

RES = SPMAT.dot(G) 

यह केवल 541ms लेता है:

RES = n.zeros((SPMAT.shape[0],),dtype=complex64) 
RES.real = SPMAT.dot(G.real); RES.imag = SPMAT.dot(G.imag) 

और परिणाम समान है। मुझे लगता है कि शायद n.zeros प्रीलोकेशन स्वीकार्य नहीं हो सकता है लेकिन मुझे नहीं पता कि यह और कैसे करें।

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