2010-02-04 7 views
18

मैं पाइथन का उपयोग करके रूपांतरण के प्रदर्शन में सुधार करना चाहता हूं, और प्रदर्शन में सुधार के बारे में कुछ बेहतरीन जानकारी के बारे में कुछ अंतर्दृष्टि की उम्मीद कर रहा था।नम्पी प्रदर्शन में सुधार

मैं वर्तमान में scipy उपयोग कर रहा हूँ घुमाव के प्रदर्शन करने के लिए, कुछ हद तक नीचे स्निपेट कैसा कोड का उपयोग:

import numpy 
import scipy 
import scipy.signal 
import timeit 

a=numpy.array ([ range(1000000) ]) 
a.reshape(1000,1000) 
filt=numpy.array([ [ 1, 1, 1 ], [1, -8, 1], [1,1,1] ]) 

def convolve(): 
    global a, filt 
    scipy.signal.convolve2d (a, filt, mode="same") 

t=timeit.Timer("convolve()", "from __main__ import convolve") 
print "%.2f sec/pass" % (10 * t.timeit(number=10)/100) 

मैं छवि डेटा संसाधित कर रहा हूँ, ग्रेस्केल का उपयोग कर (0 और 255 के बीच पूर्णांक मान), और मैं वर्तमान में मिल एक प्रति सेकंड एक रूपांतरण के बारे में एक चौथाई। मेरी सोच निम्नलिखित में से एक करना था:

कोरपी का प्रयोग करें, अधिमानतः कुछ अनुकूलन आईसीसी & ikml के साथ रिकॉम्पाइल numpy। पायथन-कूडा का प्रयोग करें।

मैं सोच रहा था कि अगर इनमें से किसी भी दृष्टिकोण (किसी प्रकार का लाभ सामान्य होगा, और यदि यह समय के लायक है) के साथ कोई अनुभव था, या अगर किसी को नाम्पी के साथ दृढ़ संकल्प करने के लिए बेहतर लाइब्रेरी के बारे में पता है।

धन्यवाद!

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

स्पीड 10x के बारे में फिर से लेखन अजगर पाश द्वारा सी में Numpy का उपयोग करने पर निर्भर है।

उत्तर

10

2 डी convolutions करने के लिए scipy में कोड थोड़ा गन्दा और unoptimized है। http://svn.scipy.org/svn/scipy/trunk/scipy/signal/firfilter.c देखें यदि आप निचले स्तर के निम्न स्तर के कामकाज में झलक चाहते हैं।

इस तरह एक समारोह काम हो सकता है सब आप चाहते हैं एक तुम से पता चला है, जैसे एक छोटे, लगातार कर्नेल के साथ कार्रवाई करने के लिए है, तो:

def specialconvolve(a): 
    # sorry, you must pad the input yourself 
    rowconvol = a[1:-1,:] + a[:-2,:] + a[2:,:] 
    colconvol = rowconvol[:,1:-1] + rowconvol[:,:-2] + rowconvol[:,2:] - 9*a[1:-1,1:-1] 
    return colconvol 

इस समारोह कर्नेल का पृथकत्व का लाभ लेता है DarenW तरह का सुझाव दिया ऊपर, साथ ही अधिक अनुकूलित numpy अंकगणित दिनचर्या का लाभ लेना। यह मेरे माप द्वारा convolve2d समारोह से 1000 गुना तेज है।

+0

यह इंगित करने के लिए धन्यवाद कि, मैंने यह नहीं सोचा था कि scipy convolve अक्षम हो सकता है। ऐसा लगता है, यद्यपि मैंने उस बारीकी से जांच नहीं की है, वह समझदार दृढ़ संकल्प मेमोरी मैनिपुलेशन ऑपरेशंस का थोड़ा सा कर रहा है और इसमें कई संख्याएं हैं जो चीजों को धीमा कर देती हैं। मैं परिणाम वापस पोस्ट करूंगा, और आपकी टिप्पणियों के लिए सभी को धन्यवाद दूंगा। – Bear

+1

हां, convolve2d काफी अक्षम है, क्योंकि यह सामान्य मामले से संबंधित है (यह मनमानी वस्तुओं से संबंधित है - उदाहरण के लिए, आप दशमलव वस्तुओं की सरणी के साथ घूमने में सक्षम होना चाहिए)। मुझे लगता है कि यह सामान्य मामले के लिए विशेष कोडपैथ का उपयोग करके काफी बढ़ाया जा सकता है (विशेष रूप से ट्रिपल लूप के अंदर फ़ंक्शन पॉइंटर कॉल से बचने के लिए, जो होस्टपॉट में से एक होने की संभावना है। –

0

संकल्प के लिए एक सामान्य अनुकूलन आपके सिग्नल के एफएफटी का उपयोग करना है। कारण यह है: वास्तविक अंतरिक्ष में संकल्प एफएफटी अंतरिक्ष में एक उत्पाद है। सामान्य रूप से एफएफटी, फिर उत्पाद, और आईएफएफटी को सामान्य तरीके से संकलित करने की तुलना में अक्सर तेज़ी से होता है।

+0

और CUDA के साथ ऐसा करते हैं, और यह वास्तव में बहुत हो जाएगा तेजी से। यदि कूडा लक्षित वातावरण में काम करता है, तो यह सबसे अधिक प्रदर्शन प्राप्त करने की संभावना है ... जीपीयू वास्तव में बहुत तेज हैं। सीयूए जीतने का एकमात्र तरीका यह नहीं है कि यदि GPU में डेटा स्थानांतरण और समय पर हावी होना शुरू हो जाता है। –

+0

मैं चाहता हूं कि वीडियो कार्ड के बीच डेटा स्थानांतरण आगे बढ़ेगा! पूर्व मौजूदा पुस्तकालयों के लिए कोई सुझाव? – Bear

+2

चौकोर चाल बड़े संकल्प कर्नेल के लिए अच्छा है, लेकिन उदाहरण के लिए, यह केवल 3x3 है। बस रास्ता शायद तेज़ है - लेकिन अगर एफएफटी सीयूडीए का उपयोग करता है, जबकि बस रास्ता नहीं है, तो मापने वाला कोई भी नहीं बता रहा है। – DarenW

2

विशिष्ट उदाहरण 3x3 कर्नेल के लिए, मैं पालन करता हूँ कि

1 1 1 
1 -8 1 
1 1 1 

    1 1 1  0 0 0 
= 1 1 1 + 0 -9 0 
    1 1 1  0 0 0 

और कहा कि इनमें से पहला factorable है - यह प्रत्येक पंक्ति के लिए convolving (1 1 1) द्वारा घुमावदार किया जा सकता है, और उसके बाद फिर प्रत्येक कॉलम के लिए। फिर मूल डेटा नौ गुना घटाएं। यह तेजी से हो सकता है या नहीं भी हो सकता है, इस पर निर्भर करता है कि क्या scipy प्रोग्रामर ने इसे स्वचालित रूप से करने के लिए पर्याप्त स्मार्ट बनाया है। (मैंने थोड़ी देर में चेक नहीं किया है।)

शायद आप अधिक दिलचस्प संकल्प करना चाहते हैं, जहां फैक्टरिंग संभव हो सकती है या नहीं भी हो सकती है।

1

सीटीपीएस के साथ सी कहने से पहले, मैं सी में एक स्टैंडअलोन कन्वोल्यू चलाने का सुझाव देता हूं, यह देखने के लिए कि सीमा कहां है। CUDA, cython, scipy.weave के लिए इसी तरह
...

जोड़ा 7feb: convolve33 कतरन के साथ 8 बिट डेटा बिंदु प्रति 20 घड़ी चक्र, 2 मेम पहुँच प्रति घड़ी चक्र लेता है ~, के साथ अपने मैक g4 पीसीसी पर जीसीसी 4.2।आपका माइलेज अलग-अलग होगा।

बारीकियों के एक जोड़े:

  • आप 0..255 करने के लिए सही कतरन के बारे में परवाह करते हैं? np.clip() धीमा है, साइथन आदि पता नहीं है।
  • Numpy/scipy को ए के आकार के लिए स्मृति की आवश्यकता हो सकती है (इसलिए 2 * आकार (ए) < कैश आकार रखें)।
    यदि आपका सी कोड, हालांकि, एक चल रहे अद्यतन इनस्थल करता है, तो यह आधा मेम है लेकिन एक अलग एल्गोरिदम है।

वैसे, गूगल theano convolve => "एक घुमाव के सेशन कि scipy.signal.convolve2d की नकल करना चाहिए, लेकिन तेजी से! घटनाक्रम में"